먼저 Router 부터 설정한다.

사용자가 홈, TV 채널, 검색 페이지로 이동할 수 있는 단순한 네비게이션을 구현하고, Header를 통해 모든 페이지에서 공통적으로 보여지는 컴포넌트를 추가했다.
넷플릭스에 들어가게 되면, 제일 먼저 볼 수 있는 상단 즉 Header 부분을 만들어보자

정말 간단하게 styled-components를 사용하여 네비게이션 바를 만들어 보았는데, 이는 공통적으로 보이는 컴포넌트이고, 네비게이션 바는 브라우저 상단에 고정되어 있으며, 좌우로 나뉘어진 두 개의 열로 구성되어 있다.

첫번째 : Logo fillOpacity animation 주기
두번째 : 페이지 이동할 때마다, 빨간색 점 으로 이동한 지 알려주기!

NETFLEX 로고 (svg)의 path에 motion.path로 지정해두고,
로고에 마우스를 올렸을 때, 발생할 animation을 지정하면 된다!
--> varients 속성을 사용하면 된다

logoVarients는 Logo 컴포넌트의 애니메이션 변형(variants)들을 정의하는 객체이다.
두 가지 상태를 가지고 있으며, Logo 컴포넌트가 초기에는 nomal 상태에 있다가, 마우스를 올렸을 때(whileHover) active 상태로 전환된다.
이렇게 하면 마우스를 Logo 컴포넌트에 올렸을 때 로고의 투명도가 애니메이션을 통해 변경되며 반복적으로 변화하는 애니메이션을 확인할 수 있다!
여기서 생각해봐야할 점은,
만약 home으로 이동했을 때, 이동한 위치가 지정한 경로가 일치했을 때, 빨간색 점을 띄운다. 라고 생각했을 때, 그럼 이동한 위치가 지정한 경로가 일치한지 안한지는 어떻게 알지 ?
useMatch 를 사용하면 된다!
useMatch는 react-router-dom에서 제공하는 훅으로, 현재 URL이 특정 경로와 일치하는지를 검사하고, 일치할 경우 경로의 매칭 정보를 반환한다.
const homeMatch = useMatch('/');
const tvMatch = useMatch('/tv');
homeMatch에는 현재 URL이 "/"과 일치하면 그 정보가 객체 형태로, 일치하지 않으면 null이 들어가게 된다.
tvMatch도 마찬가지이다!

Link:
to="/"와 to="/tv"는 각각 루트(Home)와 tv 경로로 연결된다.homeMatch:
tvMatch:
이렇게 클릭했을 때, url일치한 지 확인한 후, 링크에 맞춰서 빨간색 버튼이 생성이 되는 것을 확인할 수 있다!

돋보기 이미지를 누르면 input창이 등장하고, 돋보기 이미지도 함께 이동한다!
이후, 돋보기 이미지를 다시 누르면 닫히는 애니메이션을 추가해보자
const [searchOpen, setSearchOpen] = useState(false);
const toggleSearch = () => {
setSearchOpen((prev) => !prev);
};
useState(false)는 searchOpen 상태를 초기값 false로 설정하고, 이를 변경할 수 있는 setSearchOpen 함수를 제공한다.
toggleSearch 함수는 searchOpen 상태를 반전시킨다. 이 함수가 호출될 때마다 searchOpen은 false에서 true, true에서 false로 토글된다.

<motion.svg> :
animate={{ x: searchOpen ? -180 : 0 }} : searchOpen 상태에 따라 아이콘의 x축 위치를 -180 픽셀로 이동하거나 원래 위치로 이동한다. 이로 인해 검색창이 열리거나 닫힐 때 아이콘이 이동한다.transition={{ type: 'linear' }} : 애니메이션의 전환 유형을 선형으로 설정한다.<Input>:
animate={{ scaleX: searchOpen ? 1 : 0 }} : searchOpen 상태에 따라 x축 방향으로 확대되거나 축소된다. scaleX: 1은 원래 크기를 의미하며, scaleX: 0은 축소된 크기를 의미한다.이로써 Input창과 motion.svg는 애니메이션을 작동하게 된다!
구글 폰트로 Logo만들기 이 사이트에 들어가면 구글 폰트로 SVG만들 수 있다!
원하는 폰트 찾아서 복사하면 되는데!

대충 이런식으로 나온다!
똑같이 복사하고, 적용시키면 된다!

쿠쿠 S-FLEX멋있게 나온걸 알 수 있다.
useAnimation()를 사용하면 시작 및 중지 메서드가 있는 AnimationControls을 만들 수 있다.
기존에
const toggleSearch = () => {
setSearchOpen((prev) => !prev);
};
<Input
placeholder="Search for movie or tv show ..."
animate={{ scaleX: searchOpen ? 1 : 0 }}
transition={{ type: 'linear' }}
/>
이러한 코드를 useAnimation() 를 사용해서 변수로 animation을 만들 수 있다.
const inputAnimation = useAnimation();
const toggleSearch = () => {
if (searchOpen) {
inputAnimation.start({
scaleX: 0,
});
} else {
inputAnimation.start({
scaleX: 1,
});
}
setSearchOpen((prev) => !prev);
};
inputAnimation을 animate에 적어두고, initial 즉 초기 상태도 적어주어야 한다..
나는 아무래도 첫 번째 방법이 더 편한 것 같다 호호!!
스크롤하면 떠올라야 하는 것은 ? useScroll (useViewportScroll" 은 "useScroll" 로 변경)
useScroll로 y축의 값을 얻어온 다음, 그 범위로 배경색 변경이 되도록 애니메이션이 이루어져야 한다.

1 . navVariants 객체
navVariants는 두 가지 상태 (top, scroll)에 대한 배경색 스타일을 정의하는 객체
2 . useScroll 훅
const { scrollY } = useScroll();
: useScroll 훅은 페이지의 스크롤 위치를 추적
3 . useAnimation 훅
const navAnimation = useAnimation() ;
useAnimation 훅은 애니메이션 컨트롤러를 생성 --> start, end, stop등 다양하게 적용 가능
4 . useMotionValueEvent 훅
scrollY.get()을 사용하여 현재 스크롤 위치를 가져온다.<Nav variants={navVariants} initial="top" animate={navAnimation}>

그럼 이렇게 처음에는 투명한 배경색이였다가 스크롤을 하면 검정색으로 배경화면이 바뀌는 nav를 확인할 수 있다!