스크롤을 내리다가 해당 target에 도착하면 애니메이션이 발생하는 웹페이지를 구현해보자.
자바스크립트를 이용하여 스크롤 애니메이션을 만들 때 사용할 수 있는 것이 Intersection Observer API 이다.
intersection observer를 생성하기 위해서는 생성자 호출 시 콜백 함수를 제공해야 합니다. 이 콜백 함수는 threshold가 한 방향 혹은 다른 방향으로 교차할 때 실행됩니다.
let options = {
root: document.querySelector('#scrollArea'),
rootMargin: '0px',
threshold: 1.0
}
let observer = new IntersectionObserver(callback, options);
여기서 option이 무엇인지 알아보자.
공식 문서에 나와있는 내용이다.
Intersection observer 설정
IntersectionObserver() 생성자에 전달되는 options 객체는 observer 콜백이 호출되는 상황을 조작할 수 있습니다. 이는 아래와 같은 필드를 가집니다:
root
대상 객체의 가시성을 확인할 때 사용되는 뷰포트 요소입니다. 이는 대상 객체의 조상 요소여야 합니다. 기본값은 브라우저 뷰포트이며, root 값이 null 이거나 지정되지 않을 때 기본값으로 설정됩니다.
rootMargin
root 가 가진 여백입니다. 이 속성의 값은 CSS의 margin 속성과 유사합니다. e.g. "10px 20px 30px 40px" (top, right, bottom, left). 이 값은 퍼센티지가 될 수 있습니다. 이것은 root 요소의 각 측면의 bounding box를 수축시키거나 증가시키며, 교차성을 계산하기 전에 적용됩니다. 기본값은 0입니다.
threshold
observer의 콜백이 실행될 대상 요소의 가시성 퍼센티지를 나타내는 단일 숫자 혹은 숫자 배열입니다. 만일 50%만큼 요소가 보여졌을 때를 탐지하고 싶다면, 값을 0.5로 설정하면 됩니다. 혹은 25% 단위로 요소의 가시성이 변경될 때마다 콜백이 실행되게 하고 싶다면 [0, 0.25, 0.5, 0.75, 1] 과 같은 배열을 설정하세요. 기본값은 0이며(이는 요소가 1픽셀이라도 보이자 마자 콜백이 실행됨을 의미합니다). 1.0은 요소의 모든 픽셀이 화면에 노출되기 전에는 콜백을 실행시키지 않음을 의미합니다.
간단한 사용법은 다음과 같다.
여기에 옵션 추가 및 원하는 내용으로 수정.
let observer = new IntersectionObserver((e)=>{
e.forEach((box))=>{
if(box.isIntersecting){
box.target.style.opacity = 1
}
else{
box.target.style.opacity = 0
}
}
})
let target = document.querySelector('div');
observer.observe(target[0]);
observer.observe(target[1]);
observer.observe(target[2]);
물론 이렇게 자바스크립트로만 작성하면 너무 복잡하므로 라이브러리를 이용하자.
아래는 framer-motion을 이용한 스크롤 이벤트이다.
import { motion, Variants } from "framer-motion";
const cardVariants: Variants = {
offscreen: {
y: 300,
},
onscreen: {
y: 50,
rotate: -10,
transition: {
type: "spring",
bounce: 0.4,
duration: 0.8,
},
},
};
export const testApp = () =>{
return (
<motion.div
className="card-container h-screen w-full bg-black"
initial="offscreen"
whileInView="onscreen"
viewport={{ once: false, amount: 0.5 }}
//amount = 이 div가 얼마나 보였을 때 작동할지. 0.5 = 50%
//once는 한 번만 실행할지 아닐지 설정
//부모 div에서 initial(시작), whileInView(보였을때), viewport 설정하고
>
<motion.div
className="card h-52 w-52 bg-white"
variants={cardVariants}
>
//애니메이션을 구현할 자식요소에서 variants 설정
</motion.div>
</motion.div>
)
}
div가 화면의 50%가 넘는 순간 아래 사진처럼 애니메이션 작동!