[CSS] 화면에 컴포넌트가 나타났을 때 실행되는 애니메이션 custom hook으로 만들기
2024. 3. 22. 18:24
반응형
세로로 긴 스크롤을 쭉쭉 내리다가, 특정 컴포넌트가 mount 됐을 때 애니메이션이 실행되도록 해야한다.
같은 방식으로 동작하는 컴포넌트들이 여기저기 여러번 쓰여서, 커스텀 훅으로 만들어 쓰기로 했다.
(Next.js14 & Styled-components 사용 환경이다.)
Custom hook
// useScrollAnimation.tsx
'use client';
import { useEffect, useState, RefObject } from 'react';
const useScrollAnimation = (ref: RefObject<HTMLElement>) => {
const [isInViewport, setIsInViewport] = useState(false);
useEffect(() => {
if (!ref.current) return;
const callback = (entries: IntersectionObserverEntry[]) => {
entries.forEach((entry) => {
// 요소가 뷰포트에 나타났을 때
if (entry.isIntersecting) {
setIsInViewport(true);
}
// 요소가 뷰포트를 벗어났을 때
else {
setIsInViewport(false);
}
});
};
const options = { root: null, rootMargin: '0px', threshold: 0 };
const observer = new IntersectionObserver(callback, options);
observer.observe(ref.current); // 요소 관찰 시작
console.log(isInViewport);
return () => {
observer.disconnect(); // 컴포넌트 언마운트시 관찰 중단
};
}, []);
return { isInViewport };
};
export default useScrollAnimation;
(참고: 키프레임 모음집)
// keyframes.ts
import { keyframes } from 'styled-components';
export const Floating = keyframes`
0% { transform: translateY(0);}
50% { transform: translateY(-25px);}
100% { transform: translateY(0);}
`;
export const FadeInUp = keyframes`
0% { opacity: 0; transform: translate3d(0, 75%, 0);}
to { opacity: 1; transform: translateZ(0);}
`;
위에서 만든 커스텀훅을 가져다가 사용하는 부분
import styled from 'styled-components;
import useScrollAnimation from 'hooks/useScrollAnimation';
import { FadeInUp } from 'styles/keyframes';
import { useRef } from 'react';
const MyComponent = () => {
const ref = useRef<HTMLDivElement | null>(null);
const { isInViewport } = useScrollAnimation(ref);
...
return (
<div ref={ref}>이 컴포넌트가 화면에 나타나는게 애니메이션 시작하라는 신호!
<Target>애니메이션이 적용될 컴포넌트</Target>
</div>
)
}
...
const Target = styled.div<{$isAnimate: boolean}>`
${(props) => props.$isAnimate &&
css ` animation: ${FadeInUp} 1s`
}
`
반응형
'한 걸음 > HTML & CSS' 카테고리의 다른 글
[CSS] 텍스트 앞에 붙은 Dot이 찌그러질 때 (0) | 2024.03.22 |
---|---|
[CSS] parrent layout 무시하고 width 100% 꽉 채우기 (0) | 2024.03.12 |
[React + styled-componenets] 커스텀 range slider 만들기 (0) | 2023.10.23 |
[CSS] 가변적인 길이의 컴포넌트에서 형제요소 width에 max-width맞추기 (0) | 2023.07.06 |
[CSS] 순수 CSS로 섹션별 스크롤 기능 만들기 (0) | 2023.03.04 |