- Published on
Intersection Observer
- Author
- Name
- yceffort
Intersection Observer
Intersection Observer는 엘리먼트가 viewport에 노출되고 있는지 여부를 확인해주는 API다. 간단히 말해 브라우저의 어떤 요소가 화면에 노출되고 있는지 안되고 있는지를 확인해주는 라이브러리라고 생각하면 될 것 같다. 이 라이브러리가 없이 엘리먼트가 노출중인지 확인하려면 어떻게 해야할까? 이전까지 주로 사용되던 API는 getBoundingClientRect다. 이 메서드는 해당 엘리먼트의 크기와 viewport에서의 상대적인 위치를 알려준다.
function isInViewport(element) {
// viewport의 height, width
const viewportHeight = document.documentElement.clientHeight
const viewportWidth = document.documentElement.clientWidth
// 엘리먼트의 rect
const rect = element.getBoundingClientRect()
if (!rect.width || !rect.height) {
return false
}
var top = rect.top >= 0 && rect.top < viewportHeight
var bottom = rect.bottom >= 0 && rect.bottom < viewportHeight
var left = rect.left >= 0 && rect.left < viewportWidth
var right = rect.right >= 0 && rect.right < viewportWidth
return (top || bottom) && (left || right)
}
물론 이 함수로도 충분히 확인이 가능하다. 그러나 문제는 이 함수를 시도 때도 없이 불러야 할것이다. 문서가 처음로딩 되었을때, 스크롤 이벤트가 발생했을때, 브라우저 크키가 변경되었을때, (모바일의 경우) 화면이 회전 됐을 때 등 고려해야할 사황이 너무나도 많다. 그리고 결정적으로 getBoudingClientRect()
는 호출이 될 때 마다 레이아웃을 다시 그리기 때문에 성능에 매우 부담이 간다. 참고
사용법
var options = {
root: document.querySelector('#scrollArea'),
rootMargin: '0px',
threshold: 1.0,
}
var observer = new IntersectionObserver(callback, options)
root
: 엘리먼트 노출을 감시할 viewport 영역이다. null이 기본값이고, null이라면 브라우저 전체를 감시하게 된다.
rootMargin
: css의 margin property와 사용법이 같다. root에 margin 값을 주는 것이다.
threshold
: number, 또는 array of number가 가능하다. 여기서 숫자는 viewport의 n%가 되었을 때 이벤트를 호출할 것인지 결정하는 것이다. array라면 해당 숫자만큼 노출될때 마다 이벤트가 발생하게 된다. 기본값은 0 으로, 단 1픽셀이라도 노출될 경우 이벤트가 발생된다.
callback
: 타겟이 노출될때 실행되는 콜백함수다. 여기서는 두개의 값을 반환한다.
entries
: IntersectionObserverEntry의 array이며, 각각 얼마나 노출되었는지 값이 나온다.
observer
: callback을 호출한 IntersectionObserver
var target = document.querySelector('#listItem')
observer.observe(target)
https://codepen.io/yceffort/pen/RzVyML
콘솔창을 보면, 50% 이상 나온 엘리먼트가 찍히는 것을 볼 수 있다.
활용해보기
무한스크롤
https://codepen.io/yceffort/pen/VJbxNM
문서의 맨 마지막에 height가 10px인 #watch_end_of_document
를 넣어서, 이 엘리먼트가 브라우저에 노출되게 되면 스크롤의 마지막에 온것으로 간주하고 그 때마다 새로운 아이템들을 로딩하도록 명령을 내렸다.
이미지 레이지 로딩
https://codepen.io/yceffort/pen/YoVvya
콘솔 - 네트워크 창으로 가보면 이미지가 동적으로 로딩되는 것을 알 수 있다. 각각의 엘리먼트들에 observer를 걸어두고, viewport에 걸칠때 마다 backgroundImage를 줘서 이미지가 로딩되도록 하였다.