Intersection Observer란 뷰포트의 영역과 타겟 요소 영역의 중첩을 감지(Detect)하는 웹 API 기술이다.
쉽게 말해 사용자의 화면에 특정 요소가 보이는지의 여부와, 영역이 겹친 정도 등을 알려주는 비동기적 센서라고 할 수 있다.
Intersection Observer API의 강점은 지속적인 스크롤 이벤트 감지 없이도 효율적으로 리소스를 관리하면서 정확히 감지 기능을 수행한다는 점이다.
연속적인 스크롤 이벤트 감지가 무작위로 쏘아대다 맞으면 알려주는 기관총이라면 Intersection Observer는 정확히 타격점을 조준, 격발하는 스나이핑 라이플과 같다고 할 수 있다. 🎯
window.addEventListener('scroll', () => {
if (this.pageYOffset > 1000) { ... }
else if (this.pageYOffset > 2000) { ... }
...
});
비효율적인 스크롤 이벤트 감지 멈춰! ✋🏻
const observer = new IntersectionObserver(callback[, options]);
먼저 new 키워드로 새로운 IntersectionObserver 객체를 생성하는 것으로 관찰자(Observer)를 셋업한다.
생성자는 뷰포트(또는 지정된 root)에 감지되었을때 실행될 콜백과 옵션을 인자로 받는다.
const observer = new IntersectionObserver((entries, observer) => {
// ...do something...
}, options);
관찰자의 타겟이 감지되었을때 실행될 콜백에게 기본적으로 entries
와 observer
두 개의 인자가 전달된다. (addEventListener
의 콜백이 event
객체를 인자로 받는 것과 같다.)
const sections = document.querySelectorAll('section');
const io = new IntersectionObserver((entries, observer) => {
const [entry] = entries;
console.log(entry);
})
io.observe(sections[2]);
여러개의 section
이 슬라이드로 구성된 페이지에서 [2]번째 섹션의 entry 정보를 콘솔에 출력해보면 아래와 같이 IntersectionObserverEntry
객체를 배열에 담아 반환한다.
아래 프로퍼티는 모두 읽기 전용이기 때문에 새로운 값(Set)을 넣어 변화를 줄 순 없다.
IntersectionObserverEntry
의 속성들 ✅
boundingClientRect
: 관찰 대상의 Rect 정보 Read only
intersectionRatio
: 관찰 대상이 중첩된 비율 반환 (안겹치면 0
, 완전히 겹치면 1
) Read only
intersectionRect
: 관찰 대상이 중첩된 영역 정보 Read only
isIntersecting
: 관찰 대상의 중첩 여부 (true or false)
Read only
✅rootBounds
: 지정한 루트(뷰포트의 역할을 수행)의 Rect 정보 Read only
target
: 관찰 대상 요소 (DOM Element) Read only
time
: 관찰 대상이 노출된 시간 정보 (Time Stamp) Read only
intersectionRatio
의 값이0
이상일 경우root
영역에 대상이 겹쳤음을 의미하고, 이는isIntersecting
값이true
인 경우와 같다고 볼 수 있다.
즉isIntersecting: true
가 핵심 열쇠다. 🔑
root
, rootMargin
, threshold
등 관찰자 객체의 특성을 담은 객체.
let options = {
root: document.querySelector(`#targetArea`),
rootMargin: `0px`,
threshold: 1.0
}
let observer = new IntersectionObserver(callback, options);
// or
let observer = new IntersectionObserver(callback, {
root: document.querySelector(`#targetArea`),
rootMargin: `0px`,
threshold: 0
});
root
: 기본값은 null
이며 뷰포트 대신 사용할 요소를 지정할 수 있다.
rootMargin
: root
의 범위를 확장 또는 축소할 수 있다. 단위는 px
또는 %
이며 CSS
의 margin
속성 표기 방법과 똑같다. (e.g. top
right
bottom
left
)
threshold
: root
와 관찰되는 요소가 얼마나 중첩되어야 콜백을 실행할지 결정할 수 있다. 0
과 1
사이의 값으로 표현하며 배열을 넣어 중첩되는 단계별로 옵저버를 실행할 수도 있다.
- 0
: 타겟의 가장자리가 root
영역에 포착되는 순간 콜백 실행
- 1
: 타겟의 모든 영역이 root
영역에 들어오면 콜백 실행
- [0, ... , 1]
: 타겟과 root
이 중첩되는 단계별로 순차적 콜백 실행
observe()
대상 요소의 관찰을 시작 👀
const io = new IntersectionObserver(callbackFn, options);
const section = document.querySelector('#section1');
io.observe(section);
unobserve()
대상 요소의 관찰 중지 🛑
const io = new IntersectionObserver(callbackFn, options);
io.unobserve(section);
disconnect()
관찰자(IntersectionObserver 객체)의 모든 관찰을 중단 🚫
const io = new IntersectionObserver(callbackFn, options);
io.disconnect();
파란색 공이 뷰포트에 완전히 반쯤 들어오면 공 속의 숨은 메세지를 볼 수 있는 예제를 만들었다.
Observer
가 파란색 공이 뷰포트 영역 threshold
비율만큼 겹치면 isIntersecting
값을 true로 반환하며 콜백이 실행된다.
// box 클래스를 가진 DOM 요소들의 NodeList를 반환
const boxes = document.querySelectorAll('.box');
// 영역 감지되면 실행될 콜백
const animateBox = function(entries, observer) {
// Destructuring
const [{isIntersecting, target}] = entries;
// 만약 영역 감지가 true라면 class 추가, 아니면 제거
if (isIntersecting) {
target.classList.add('visible');
} else {
target.classList.remove('visible');
}
};
// intersection observer 생성자 초기화 (관찰자)
const io = new IntersectionObserver(animateBox, {
root: null,
threshold: 0.5,
})
// NodeList의 각 요소들 감시 시작
boxes.forEach(e => {
io.observe(e);
})
IE에선 전혀 지원하지 않지만 모듈을 가져옴으로써 폴리필(Polyfill)로 사용할 수 있다고 한다.
완벽하게 이해하면 다시 포스팅 할 예정
코드펜의 뷰포트 문제인지, 호환성 문제인지 잘 모르겠지만.. 해결되면 다시 업로드 예정
반면 데스크탑 브라우저에선 잘 작동된다. 🤔
// 변경 전
const io = new IntersectionObserver(animateBox, {
root: null,
threshold: 1,
})
// 변경 후
const io = new IntersectionObserver(animateBox, {
root: null,
threshold: 0.5,
})
모바일 브라우저에 표시된 코드펜의 뷰포트가 상대적으로 작아서 생긴 문제였다.
threshold
를 0.5
로 낮춰 요소 영역이 반만 뷰포트와 겹쳐도 isIntersecting = true
판정이 나도록 바꿨더니 잘 작동된다.
이제 잘 수 있을 것 같다. 💤
고마워요 Stack Overflow
References:
MDN: IntersectionObserver
HEROPY Tech: Intersection Observer - 요소의 가시성 관찰