fix: gsap 추가

This commit is contained in:
이희원 2026-06-20 02:14:00 +09:00
parent 1cdb048e36
commit 67c0bfe5b9
6 changed files with 70 additions and 40 deletions

View File

@ -19,6 +19,7 @@
"vite-plugin-imagemin": "^0.6.1"
},
"dependencies": {
"gsap": "^3.15.0",
"jquery": "^4.0.0",
"sharp": "^0.35.1"
}

View File

@ -18,7 +18,7 @@
</a>
<nav class="gnb__nav">
<ul class="gnb__navList">
<li class="gnb__navItem is-active"><a class="gnb__navLink" href="#intro">HOME</a></li>
<li class="gnb__navItem"><a class="gnb__navLink" href="#intro">HOME</a></li>
<li class="gnb__navItem"><a class="gnb__navLink" href="#about">ABOUT</a></li>
<li class="gnb__navItem"><a class="gnb__navLink" href="#project">PROJECTS</a></li>
<li class="gnb__navItem"><a class="gnb__navLink" href="#contact">CONTACT</a></li>
@ -638,7 +638,7 @@
</div>
<!-- 프로젝트 문의 -->
<div class="contactAccordion">
<div class="contactAccordion__item is-open" id="acc-project">
<div class="contactAccordion__item isOpen" id="acc-project">
<button class="contactAccordion__header" aria-expanded="true" aria-controls="acc-project-body">
<span>프로젝트 문의</span>
<img class="contactAccordion__icon" src="images/icon-chevron.svg" alt="" />

View File

@ -1,55 +1,86 @@
import $ from "jquery";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
$(function () {
const $gnb = $("#gnb");
const $hamburger = $(".gnb__hamburger");
const $mobileNav = $(".gnb__mobileNav");
const $sections = $("section[id]");
const $navLinks = $(".gnb__navItem");
// 섹션 → nav 귀속 맵
const sectionToNav = {
intro: "intro",
about: "about",
history: "about",
"boda-intro": "about",
vision: "about",
project: "project",
expertise: "project",
contact: "contact",
};
// GNB 스크롤 배경
$(window).on("scroll.gnb", { passive: true }, function () {
$gnb.toggleClass("is-scrolled", $(this).scrollTop() > 40);
updateActiveNav();
ScrollTrigger.create({
start: "40px top",
onEnter: () => $gnb.addClass("isScrolled"),
onLeaveBack: () => $gnb.removeClass("isScrolled"),
});
// 현재 섹션에 따라 GNB 활성화
const $navLinks = $(".gnb__navLink");
const sections = $("section[id]").toArray();
function setActiveNav(navId) {
$navLinks.each(function () {
const href = $(this).attr("href").replace("#", "");
$(this).toggleClass("isActive", href === navId);
});
}
function updateActiveNav() {
const scrollY = window.scrollY + window.innerHeight / 3;
let current = "";
sections.forEach((el) => {
if (el.offsetTop <= scrollY) {
current = sectionToNav[el.id] || current;
}
});
setActiveNav(current);
}
ScrollTrigger.create({
trigger: document.body,
start: "top top",
end: "max",
onUpdate: updateActiveNav,
});
updateActiveNav();
// 햄버거 메뉴
$hamburger.on("click", function () {
const isOpen = $hamburger.toggleClass("is-open").hasClass("is-open");
const isOpen = $hamburger.toggleClass("isOpen").hasClass("isOpen");
$hamburger.attr("aria-expanded", isOpen);
$mobileNav.toggleClass("is-open", isOpen);
$mobileNav.toggleClass("isOpen", isOpen);
});
// 모바일 메뉴 링크 클릭 시 닫기
$(".gnb__mobileNavLink").on("click", function () {
$hamburger.removeClass("is-open").attr("aria-expanded", false);
$mobileNav.removeClass("is-open");
$hamburger.removeClass("isOpen").attr("aria-expanded", false);
$mobileNav.removeClass("isOpen");
});
// 현재 섹션에 따라 GNB 활성화
function updateActiveNav() {
let current = "";
const scrollY = $(window).scrollTop() + $(window).height() / 3;
$sections.each(function () {
if ($(this).offset().top <= scrollY) {
current = $(this).attr("id");
}
});
$navLinks.each(function () {
const href = $(this).find("a").attr("href").replace("#", "");
$(this).toggleClass("is-active", href === current);
});
}
// Contact 아코디언
$(".contactAccordion__header").on("click", function () {
const $item = $(this).closest(".contactAccordion__item");
const $body = $("#" + $(this).attr("aria-controls"));
const isOpen = $item.hasClass("is-open");
const isOpen = $item.hasClass("isOpen");
$item.toggleClass("is-open", !isOpen);
$item.toggleClass("isOpen", !isOpen);
$(this).attr("aria-expanded", !isOpen);
if (isOpen) {
@ -58,7 +89,4 @@ $(function () {
$body.removeAttr("hidden");
}
});
// 초기 실행
updateActiveNav();
});

View File

@ -205,7 +205,7 @@
object-fit: unset;
}
.contactAccordion__item.is-open .contactAccordion__icon {
.contactAccordion__item.isOpen .contactAccordion__icon {
transform: rotate(180deg);
}

View File

@ -11,7 +11,7 @@
z-index: 100;
transition: background 0.4s;
&.is-scrolled {
&.isScrolled {
background: rgba($color-bg, 0.92);
backdrop-filter: blur(12px);
}
@ -63,7 +63,7 @@
}
}
.gnb__navItem.is-active .gnb__navLink {
.gnb__navLink.isActive {
color: $color-cyan;
}
@ -90,13 +90,13 @@
opacity 0.3s;
}
.gnb__hamburger.is-open .gnb__hamburgerLine:nth-child(1) {
.gnb__hamburger.isOpen .gnb__hamburgerLine:nth-child(1) {
transform: translateY(6px) rotate(45deg);
}
.gnb__hamburger.is-open .gnb__hamburgerLine:nth-child(2) {
.gnb__hamburger.isOpen .gnb__hamburgerLine:nth-child(2) {
opacity: 0;
}
.gnb__hamburger.is-open .gnb__hamburgerLine:nth-child(3) {
.gnb__hamburger.isOpen .gnb__hamburgerLine:nth-child(3) {
transform: translateY(-6px) rotate(-45deg);
}
@ -116,7 +116,7 @@
opacity 0.35s ease;
pointer-events: none;
&.is-open {
&.isOpen {
transform: translateY(0);
opacity: 1;
pointer-events: auto;

View File

@ -29,6 +29,7 @@ export default defineConfig({
plugins: [
{
name: 'remove-module-attrs',
apply: 'build',
transformIndexHtml(html) {
return html
.replace(/ type="module"/g, '')