특정 요소(타겟 요소)가 타겟 요소의 부모나 viewport에 교차하는지를 비동기적으로 감지해서 교차할때마다 콜백함수를 호출하는 API
이를 이용하여 스크롤 동작에 관련된 기능을 구현할 수 있다.
const io = new IntersectionObserver(callback, {
root: null, // 또는 scrollable 한 element
rootMargin: '0px', // 아무것도 안쓰면 0px,
threshold: 0.5 // 0.0 부터 1.0 사이의 숫자를 지정할 수 있습니다. 배열 값도 가능
})
root 의 값은 Element 또는 null
target (관측 대상)을 감싸는 element를 지정하는 것인데
만약 null 로 지정한다면 viewport가 된다.
root 요소를 감싸는 margin 값을 지정한다.
문자열로 작성해야 하며, css의 margin 처럼 px 또는 % 단위로 작성할 수 있다.
threshold나 교차 상태를 점검할 때 margin 값이 지정 되어 있다면, 이를 활용하여 계산이 된다.
target element가 root 와 몇 % 교차했을 때, callback을 실행할지 결정하는 값이다.
threshold: 0.5 라면 스크롤 하는 중에 element 가 50% 보였을 때 실행할 callback을 실행한다.
요소가 관측됐을 때 실행시킬 함수
무한 스크롤 구현에는 여러 가지 방법이 있는데 IntersectionObserver를 이용하면 코드나 성능상으로도 효율성있게 구현할 수 있다.
(...)
const getCardtData = async (perPage) => {
try {
setIsLoading(true);
await axios
.get(`${SERVER}api/users?per_page=${perPage}&page=1`)
.then(function (res) {
setCardDataAPI(res.data);
setIsLoading(false);
setError(false);
});
} catch (error) {
setError(true);
}
};
useEffect(() => {
perPage !== 0 && getCardtData(perPage);
}, [perPage, error]);
const onIntersect = useCallback(
(entries) => {
if (userInput) return;
const target = entries[0];
if (target.isIntersecting) setPerpage((perPage) => perPage + 3);
},
[userInput]
);
useEffect(() => {
if (!loader.current) return;
const io = new IntersectionObserver(onIntersect, { threshold: 1 });
io.observe(loader.current);
return () => io && io.disconnect();
}, [loader, userInput]);
(...)
<div ref={loader} className="loader">
{isLoading && <Spinner />}
</div>
나는 로딩 스피너를 보여주는 엘리먼트가 관측되면 카드를 추가로 받아서 보여주는 무한 스크롤을 구현했다.
스크롤을 내려가면서 엘리먼트가 관측됬을 때 애니메이션이 발생하도록 할 수 있다.
const options = {
root: null,
rootMargin: "0px 0px 30px 0px",
threshold: 0,
};
useEffect(() => {
const io = new IntersectionObserver((entries, observe) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add("active");
observe.unobserve(entry.target);
}
});
}, options);
const boxes = document.querySelectorAll(".box");
boxes.forEach((el) => {
io.observe(el);
});
}, []);
box class의 엘리먼트가 관측됬을때 아래에서 올라오는 애니메이션을 구현 했다.
https://animista.net/play/basic/slide[링크텍스트]
이번에 알게된 사이트인데 다양한 애니메이션 효과와 그 코드를 볼 수 있는 너무너무나 유용한 사이트이다.