타겟 요소와 상위 요소( or document viewport ) 사이의 intersection 내의 변화를 비동기적으로 관찰하는 방법.
요소의 가시성, 두 요소의 상대적인 가시성을 탐지하는 일
필요성
- 페이지 스크롤할 때, 컨텐츠를 지연로딩으로 불러오게 하기 위해
- 페이지를 스크롤할 때, 더 많은 컨텐츠 로드 및 렌더링 ( 페이지네이션 )
- 광고 수익 계산
- 사용자에게 보일 때만 발생하는 작업들
page scroll은 모든 요소가 메인 스레드에서 실행되기 때문에 성능 문제 발생 가능성 농후
IO API
- 감시 요소가 다른 요소에 들어가거나 나갈 때, 겹치는 부분이 변경될 때 콜백 함수가 실행된다.
- 사이트는 요소 교차를 지켜보기 위해 메인 스레드 사용할 필요 X. 비동기로 실행.
메소드
IntersectionObserver.observe( tE )
IntersectionObserver.unobserve( tE )
IntersectionObserver.disconnect( tE )
컨셉 및 사용
1) target이 root(기기 뷰포트나 특정 요소)와 교차
2) observer가 target을 감지할 때마다 콜백 호출
생성
let options = {
root: document.querySelector('#scrollArea'), //
rootMargin: '0px', //
threshold: 1.0 // target이 root에서 얼마나 보여질 것인지
}
let observer = new IntersectionObserver(callback, options);
타겟팅
let target = document.querySelector('#listItem');
observer.observe(target);
콜백함수가 처음으로 실행
이제 타겟이 IO의 threshold 만날 때마다 콜백 호출하고, 콜백은 Entry 객체 리스트를 받는다
콜백함수
let callback = (entries, observer) => {
entries.forEach(entry => {
// Each entry describes an intersection change for one observed
// target element:
// entry.boundingClientRect
// entry.intersectionRatio
if (entry.intersectionRatio > 0) {
entry.target.classList.add('tada');
}
// 그 외의 경우 'tada' 클래스 제거
else {
entry.target.classList.remove('tada');
}
// entry.intersectionRect
// entry.isIntersecting
// entry.rootBounds
// entry.target
// entry.time
});
};
메인 스레드에서 실행. 따라서 가능한 빠르게 실행되어야 함.
Andres Gallo, Lazy Load Images with Vanilla JavaScript and Intersection Observer
const images = document.querySelectorAll("img");
const imgOptions = {};
const imgObserver = new IntersectionObserver((entries, imgObserver) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return; // 어떤 이벤트 X
const img = entry.target;
img.src = img.src.replace("w=10&", "w=800&");
imgObserver.unobserve(entry.target); // 이미 받은 이미지는 다시 fetch 하지 않도록
});
혹은
entries.forEach((entry) => {
if(entry.isIntersecting) {
const lazyImage = entry.target
lazyImage.src = lazyImage.dataset.src // dataset의 src를 src로
}
})
}, imgOptions);
// observe 달기
images.forEach((img) => {
imgObserver.observe(img);
});
'JS' 카테고리의 다른 글
배열 Array: 루프 (0) | 2021.03.08 |
---|---|
중첩된 async await (0) | 2021.03.08 |
Fetch API (0) | 2021.03.05 |
Array-like objects, NodeList, HTMLCollection (0) | 2021.03.04 |
배열 Array: 아이템 추가 및 삭제, flat( ) (0) | 2021.03.03 |
댓글