TIL no.64 - IntersectionObserver
IntersectionObserver API
특정 요소(타겟 요소)가 타겟 요소의 부모나 viewport에 교차하는지를 비동기적으로 감지해서 교차할때마다 콜백함수를 호출하는 API
특정 요소(타겟 요소)가 타겟 요소의 부모나 viewport에 교차하는지를 비동기적으로 감지해서 교차할때마다 콜백함수를 호출하는 API
이를 이용하여 스크롤 동작에 관련된 기능을 구현할 수 있다.
- 비동기 무한 스크롤 UI
- 스크롤 위치에 따른 애니메이션 UI
객체 생성과 callback, root, rootMargin, threshold
const io = new IntersectionObserver(callback, {
root: null, // 또는 scrollable 한 element
rootMargin: '0px', // 아무것도 안쓰면 0px,
threshold: 0.5 // 0.0 부터 1.0 사이의 숫자를 지정할 수 있습니다. 배열 값도 가능
})
1. root
root 의 값은 Element 또는 null
target (관측 대상)을 감싸는 element를 지정하는 것인데
만약 null 로 지정한다면 viewport가 된다.
2. rootMargin
root 요소를 감싸는 margin 값을 지정한다.
문자열로 작성해야 하며, css의 margin 처럼 px 또는 % 단위로 작성할 수 있다.
threshold나 교차 상태를 점검할 때 margin 값이 지정 되어 있다면, 이를 활용하여 계산이 된다.
3. threshold
target element가 root 와 몇 % 교차했을 때, callback을 실행할지 결정하는 값이다.
threshold: 0.5 라면 스크롤 하는 중에 element 가 50% 보였을 때 실행할 callback을 실행한다.
4. 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[링크텍스트]
이번에 알게된 사이트인데 다양한 애니메이션 효과와 그 코드를 볼 수 있는 너무너무나 유용한 사이트이다.
Author And Source
이 문제에 관하여(TIL no.64 - IntersectionObserver), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@playck/TIL-IntersectionObserver저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)