Framer Motion과 Intersection Observer을 사용해 특정 요소가 화면에 보일 때 애니메이션이 동작하도록 해보려고 한다.
보통 랜딩페이지같은 부분에 사용을 하게 될 것 같은데 알아두면 여기저기 사용 가능할 것 같다.
npm install framer-motion react-intersection-observer
우선 당연한거지만 다운을 받아주게 된다.
완성된 코드부터 보자면
import { motion } from 'framer-motion';
import { useInView } from 'react-intersection-observer';
function Animate(){
// Intersection Observer 설정
const { ref, inView } = useInView({
triggerOnce: true,
threshold: 0.1,
});
return (
<div ref={ref}>
<motion.div
initial={{ opacity: 0, y: 50 }}
animate={{ opacity: inView ? 1 : 0, y: inView ? 0 : 50 }}
transition={{ duration: 0.5 }}
>
모션이 들어갈 곳
</motion.div>
</div>
);
};
export default Animate;
이런식으로 나오게 된다
하나씩 보자면 우선 useInView를 통해 요소가 뷰포트에 들어왔는지 감지를 하게 된다.
이 부분을 좀 더 보면
const { ref, inView } = useInView({
triggerOnce: true, // 한번만 트리거 되도록 설정
threshold: 0.1, // 10%가 보이면 트리거
});
이런 뜻이다.
그리고 이것을 이용해 감지를 하게 되면 motion.div에 있는 Initial과 animate를 이용해 애니메이션 상태를 설정한다.
위 코드같은 경우 animate에서 옵저버로 감지한 inView가 트루값이 들어오면 동작하도록 조건문을 걸어둔 것이다.
추가적으로 이것을 만약 컴포넌트로 빼두고 사용한다면
import { motion } from "framer-motion";
import { useInView } from "react-intersection-observer";
interface aProps {
prop : String
}
function Box({ prop }:aProps) {
const { ref, inView } = useInView({
triggerOnce: true,
threshold: 0.1,
});
return (
<>
{prop === "left" ? (
<div ref={ref} style={{ height: "500px", marginBottom: "20px" }}>
<motion.div
initial={{ opacity: 0, x: -500 }}
animate={{ opacity: inView ? 1 : 0, x: inView ? 0 : -50 }}
transition={{ duration: 1 }}
style={{ height: "500px", background: "pink", width: "500px" }}
/>
</div>
) : (
<div ref={ref} style={{ height: "500px", marginBottom: "20px" }}>
<motion.div
initial={{ opacity: 0, x: 500 }}
animate={{ opacity: inView ? 1 : 0, x: inView ? 0 : 50 }}
transition={{ duration: 1 }}
style={{ height: "500px", background: "pink", width: "500px" }}
/>
</div>
)}
</>
);
}
export default Box;
임의로 분홍색의 사각형을 만들어 받은 prop값에 따라 좌측,우측에서 나오도록 설정을 해보았다.
불러오는 곳에서는 간단하게
import Box from "@/components/scroll/Box";
import React from "react";
function Scroll() {
return (
<div>
<div style={{ height: "100vh" }}>스크롤</div>
<Box a={"left"} />
<Box a={"right"} />
<Box a={"left"}/>
<Box a={"right"}/>
</div>
);
}
export default Scroll;
이런식으로 사용하면 될 것이다.
위 코드들은 동작을 보기위한 예시들이므로 실제로 사용을 할 때는 수정을 해줘야 한다.
추가적으로 Framer motion에 위에 사용한 3가지와 몇가지 속성을 보자면
1. initial
- 애니메이션의 초기 상태를 정의
- 예: initial={{ opacity: 0, y: -100 }}
2. animate
- 애니메이션의 최종 상태를 정의
- 예: animate={{ opacity: 1, y: 0 }}
3. transition
- 애니메이션의 전환을 설정
- 예: transition={{ duration: 1, ease: "easeInOut" }}
4. exit
- 요소가 DOM에서 제거될 때 애니메이션을 정의
- 예: exit={{ opacity: 0, scale: 0.5 }}
이 외에도 whileHover, whileTap, whileDrag, drag등이 있다.
useInView도 조금 더 보자면 주요 옵션들로
1. triggerOnce
- 요소가 뷰포트에 들어왔을 때 한 번만 트리거되도록 설정
- 기본값은 'false'
- 예: useInView({ triggerOnce: true })
2. threshold
- 요소가 뷰포트에 어느정도 들어와야 트리거할지를 설정
- 기본값은 '0'
- 예: useInView({ threshold: 0.5 })
3. rootMargin
- 뷰포트의 범위를 확장하거나 축소하여 트리거 시점을 조정
- css스타일의 마진 값처럼 사용
- 예: useInView({ rootMargin: '0px 0px -50px 0px' })
위에 적은것들만 잘 응용해도 엄청 많은것을 할 수 있을것 같다.
'이것저것' 카테고리의 다른 글
| next.js에서 이미지 편집기 만들기! (0) | 2024.09.09 |
|---|---|
| 다음 우편번호 api 사용해보기 (0) | 2024.07.24 |
| PWA (1) | 2024.06.13 |
| React Portal? (0) | 2024.05.26 |
| pm2 알아보기 (0) | 2024.05.22 |