Intersection Observer API

김동현·2023년 6월 28일

JavaScript

목록 보기
31/32
post-thumbnail

Intersection Observer API

Intersection observer는 기본적으로 브라우저 뷰포트(Viewport)와 설정한 요소(Element)의 교차점을 관찰하며, 요소가 뷰포트에 포함되는지 포함되지 않는지 구별하는 기능을 제공합니다.

이 기능은 비동기적으로 실행되기 때문에, scroll 같은 이벤트 기반의 요소 관찰에서 발생하는 렌더링 성능이나 이벤트 연속 호출 같은 문제 없이 사용할 수 있습니다.

const observer = new IntersectionObserver((entries, observer) => { ,,, }, options) // 관찰자 초기화

observer.observe() // 관찰 대상 등록

new IntersectionObserver()호출하여 반환된 객체를 통해 observe 메서드를 호출하여 관찰할 대상을 등록할 수 있습니다.

Parameters

IntersectionObserver 생성자 함수는 두 개의 인수를 전달받습니다.

  • (entries, observer) => { ,,, }
    : 첫 번째 인수로 전달되는 콜백 함수는 관찰 대상이 등록되거나 교차 이벤트가 발생하면 호출되는 함수입니다.
    콜백 함수가 호출될 때 전달 받는 첫 번째 인수(entries)는 관찰 대상을 요소로 갖는 배열을 전달받습니다. 관찰 대상은 아래와 같은 메서드와 프로퍼티를 갖고 있습니다

    • boundingClientRect : 관찰 대상의 사각형 정보, Element.prototype.getBoundingClientRect 메서드와 동일한 정보를 반환합니다

    • intersectionRect : 관찰 대상과 루트 요소간 교차한 영역 정보

    • isIntersecting : 관찰 대상과 루트 요소간 교차 상태를 불리언 값으로 반환

    • intersectionRatio : 관찰 대상이 루트 요소와 얼마나 교차하는(겹치는)지의 수치를 0.0과 1.0 사이의 숫자 반환

    • rootBounds : 지정한 루트 요소의 사각형 정보

    • target : 관찰 대상 요소

    • observer : 콜백이 실행되는 해당 인스턴스를 참조합니다.

  • options

    • root : 루트 요소를 설정할 수 있습니다. 생략한 경우 기본값으로 브라우저의 뷰포트가 루트 요소로 설정됩니다.

    • threshold : 콜백 함수가 실행될 루트 요소와 관찰 대상간 교차 비율을 0부터 1사이 숫자값으로 설정할 수 있습니다. 기본값은 0으로 교차되는 순간 실행되며, 만약 0.3으로 설정시 30% 교차되는 시점에 콜백 함수가 실행됩니다.

Method

  • observer : 루트 요소와 관찰 대상간 관찰을 시작하게 됩니다.

  • unobserver : 관찰 대상 요소의 관찰을 중지합니다. 이때 인수로 관찰을 중지할 관찰 대상을 전달해주어야 합니다.

  • disconnect : 모든 관찰 대상에 대해 관찰을 중지합니다.

const useTargetIntersecting = (targets: RefObject<Element>[]) => {
    const [isTargetsVisible, setIsTargetsVisible] = useState<boolean[]>(new Array(targets.length).fill(false))

    useEffect(() => {
        // 옵저버 생성
        const observer = new IntersectionObserver((entries, observer) => {
            entries.forEach((entry, i) => {
                if(!entry.isIntersecting) return
            
                const prev = isTargetsVisible.slice(0, i)
                const next = isTargetsVisible.slice(i, -1)
                setIsTargetsVisible([...prev, true, ...next])
            
                observer.unobserver(entry.target)
            })
        })
        
        // 관찰 대상 등록
        targets.forEach((target, i) => {
            if(target.current && !isTargetsVisible[i]) {
                observer.observe(target.current)
            }
        })
        
        return () => observe.disconnect()
    }
    
    return isTargetsVisible
}

export default useTargetIntersecting
profile
Frontend Dev

0개의 댓글