728x90
반응형
📌모달창 만들기
nextjs는 특별한 조치를 취하지 않으면 server component로 간주한다. 그래서 useState를 사용하려면 맨 위쪽에 "use client"; 코드를 추가해 client component로 만들어야 한다.
"use client";
import { useState, useEffect, useRef } from "react";
import gsap from "gsap";
import Link from "next/link";
import "./modal.modul.css";
export default function Modal() {
const [burgerClass, setBurgerClass] = useState("burger-bar unclicked");
const [isMenuClicked, setIsMenuClicked] = useState(false);
const extraBackgroundRef = useRef(null);
const navRef = useRef(null);
const navLinksRef = useRef([]);
const masterRef = useRef(null);
const updateMenu = () => {
if (!isMenuClicked) {
setBurgerClass("burger-bar clicked");
masterRef.current.reversed()
? masterRef.current.play()
: masterRef.current.reverse();
} else {
setBurgerClass("burger-bar unclicked");
masterRef.current.reversed()
? masterRef.current.play()
: masterRef.current.reverse();
}
setIsMenuClicked(!isMenuClicked);
};
useEffect(() => {
const nav = navRef.current;
const extraBackground = extraBackgroundRef.current;
const navLinks = navLinksRef.current;
gsap.set([extraBackground, nav], { height: "0%", skewY: 2 });
gsap.set([navLinks], { y: -20, autoAlpha: 0 });
const staggerReveal = (nodes) => {
const tl = gsap.timeline();
tl.to(nodes, {
duration: 1,
ease: "power3.inOut",
transformOrigin: "top right",
height: "100%",
minHeight: "100%",
skewY: 0,
stagger: {
amount: 0.1,
},
});
return tl;
};
const revealMenuItems = (links) => {
const tl = gsap.timeline();
tl.to(links, {
duration: 0.8,
autoAlpha: 1,
y: 0,
stagger: {
amount: 0.1,
},
});
return tl;
};
const master = gsap.timeline({ paused: true, reversed: true });
master
.add(staggerReveal([extraBackground, nav]))
.add(revealMenuItems([navLinks]), "-=0.5");
masterRef.current = master;
}, []); // Empty dependency array to run the effect only once on mount
const handleNavLinkClick = () => {
setBurgerClass("burger-bar unclicked");
setIsMenuClicked(!isMenuClicked);
masterRef.current.reverse();
};
return (
<>
<button className="burger-menu" onClick={updateMenu}>
<span className={burgerClass}></span>
<span className={burgerClass}></span>
<span className={burgerClass}></span>
</button>
<div className="nav__extra-background" ref={extraBackgroundRef}></div>
<nav className="nav" ref={navRef}>
<div className="nav__content">
<div className="nav__links" ref={navLinksRef}>
<Link
href="#intro"
className="modal_link"
onClick={handleNavLinkClick}
>
<div>Home</div>
</Link>
<Link
href="#archiving"
className="modal_link"
onClick={handleNavLinkClick}
>
<div>Archiving</div>
</Link>
<Link
href="#projects"
className="modal_link"
onClick={handleNavLinkClick}
>
<div>Projects</div>
</Link>
<Link
href="#contact"
className="modal_link"
onClick={handleNavLinkClick}
>
<div>Contact</div>
</Link>
</div>
</div>
</nav>
</>
);
}
버거메뉴 클릭시 모달창에 네비게이션 메뉴가 나오는 효과를 gsap통해 부드럽게 전환하고 있다.
const [burgerClass, setBurgerClass] = useState("burger-bar unclicked") :
- 이 상태는 햄버거 버튼의 모양을 제어하는 데 사용된다.
- 초기값을 burger-bar unclicked로 설정하여 기본 햄버거 메뉴가 나오도록 했다.
const [isMenuClicked, setIsMenuClicked] = useState(false):
- isMenuClicked는 현재 메뉴가 클릭되었는지 여부를 나타내는 상태이다.
- 초기값은 false로 설정하였다.
- 메뉴가 클릭되면 상태를 업데이트하여 메뉴가 열렸는지 혹은 닫혔는지를 추적한다.
- setIsMenuClicked(!isMenuClicked) 이 코드는 현재 값의 반대가 된다고 생각하면 된다.
extraBackgroundRef,navRef,navLinksRef,masterRef:
- 모두 초기값을 null로 설정하였다.
※useRef?
useRef는 저장공간 또는 DOM요소에 접근하기 위해 사용되는 React Hook이다. 여기서 Ref는 reference, 즉 참조를 뜻한다. 우리가 자바스크립트를 사용 할 때에는, 특정 DOM 을 선택하기 위해서 querySelector 등의 함수를 사용한다.
React를 사용하는 프로젝트에서도 가끔씩 DOM 을 직접 선택해야 하는 상황이 필요하다. 그럴때 우리는 useRef라는 React Hook을 사용한다.
react useRef 제대로 알기 -> https://2-doooo-2.tistory.com/136
masterRef.current.reversed() ? masterRef.current.play() : masterRef.current.reverse()
- master는 modal의 애니메이션을 연결한 변수로 클릭할 때마다 반대의 상태로 출력하게끔 한다.
updateMenu() 함수
- 햄버거 버튼을 클릭할 때 호출되는 함수로, isMenuClicked 상태를 업데이트하고 GSAP을 사용하여 애니메이션을 트리거한다.
handleNavLinkClick() 함수
- 네비게이션 링크를 클릭할 때 호출되는 함수로, 메뉴를 닫고 GSAP을 사용하여 애니메이션을 역재생한다.
- <Link href="#intro" className="modal_link" onClick={handleNavLinkClick} > Link 를 통해 해당 위치로 이동하고 onClick함수를 통해 모달을 역재생시킨다.
📌모달창 기능 구현 영상
728x90
반응형
'Frontend > Next.js' 카테고리의 다른 글
Next.js - 스크롤 유도 가이드 구현 (0) | 2023.12.19 |
---|---|
Next.js - 가로 스크롤 바 구현 (0) | 2023.12.19 |
Next.js 14버전 - favicon 바꾸기 (1) | 2023.11.10 |
Nextjs - next.js 구조와 img 넣는 법 (0) | 2023.11.06 |
Next.js 14버전 - Routing , Rendering, use client (0) | 2023.11.02 |