[JS_memo] IntersectionObserver

Lina Hongbi Ko·2023년 4월 14일
0

JavaScript_memo

목록 보기
6/7
post-thumbnail

IntersectionObserver

: 스크롤이나 클릭 등, 이벤트를 실행시킬 때 브라우저의 성능을 위해 쓰는 API.

<html>
	<body>
    	<div class="box">1</div>
        <div class="box">2</div>
        <div class="box">3</div>
        <div class="box">4</div>
        <div class="box">5</div>
        <div class="box">6</div>
        <div class="box">7</div>
        <div class="box">8</div>
        <div class="box">9</div>
        <div class="box">10</div>
        
        <script>
        	window.addEventListener("scroll", (event) => {
            	const boxes = document.querySelectorAll(".box");
                boxes.forEach((box)=>{
                	const rect = box.getBoundingClient();
                })
            });
        </script>
    </body>
</html>

우리는 위의 코드처럼 박스들의 정보를 스크롤할때마다 얻을 수 있다. 하지만 저것은 좋은 코드가 아니다. 왜냐하면 콜백함수는 브라우저에서 특정한 이벤트가 발생할때 수행되는데, 수행되는것은 main thread(UI thread) 위에서 동작한다. 그래서 저 콜백함수가 실행하는 동안 다른 일을 할 수 없다(동기적).
예를 들어서 저 콜백함수가 실행되는 동안 클릭하는 이벤트를 눌러도 클릭이벤트는 실행될 수 없다. 그래서 이벤트에 등록하는 함수들은 최대한 가볍고 성능이 간단한 것을 등록하는것이 좋다.

다시 코드를 자세히 보면, 각각의 박스들을 돌면서 즉, 매번 boxes의 배열을 돌면서 각각의 요소의 getBoundinClient 정보를 얻기 위해서는 브라우저 위에서 DOM요소에 레이아웃이 발생한다. 그리고 페이지에서 레이아웃이 계속 발생하니까 성능이 좋지 않다. 클릭이 될때마다 이러한 레이아웃이 발생하는것도 좋지 않은데 하물며 스크롤은 더욱 많이 발생하므로 저렇게 쓰는 것은 좋지 않다. 660번 스크롤 하게 되면 660번의 콜백함수가 실행되고 660개의 DOM요소가 만들어지고 레이아웃이 그만큼 발생하니까! 게다가 box가 아니라 일반 섹션이나 각각의 사이즈가 다른 요소들이 반복되어진다면 전역변수로 box들을 미리 지정해도 소용없다.

그래서 이때를 위해 쓰는 것이
"ItersectionObserver() API" !!

-> 비동기적으로 어떤 변화를 감지하는 API이다. 어떤 요소가 부모 컨테이너 안이나 윈도우(뷰포트) 전체 창 안에서 요소의 Intersection을 감지한다. 즉, 요소가 창 안이나 부모 안에서 교차가 되는지를 확인하는 API. 만약 문서가 자체가 엄청 길지만 뷰포트로 보는건 제한적인 상태라면, 사용자에게 보여지는 부분만 DOM요소에서 삭제했다가 사용자가 스크롤링할 때 다시 DOM요소에 등록해서 보여줄 수 있는 경우, 등 유용하게 쓰이는 API이다.

// 위의 코드를 이용해서 IntersectionObserver() api 사용하기

<html>
	<head>
    	<style>
        	.box {
            	width: 300px;
                height: 300px;
                background-color: yellow;
            }
            .box.active {
            	background-color: purple;
            }
        </style>
    </head>
	<body>
    	<div class="box>1</div>
        <div class="box>2</div>
        <div class="box>3</div>
        <div class="box>4</div>
        <div class="box>5</div>
        <div class="box>6</div>
        <div class="box>7</div>
        <div class="box>8</div>
        <div class="box>9</div>
        <div class="box>10</div>
        
        <script>
        	const boxes = document.querySelectorAll(".box");
            const options = {
            	root: null, // deafult값 (뷰포트)
                rootMargin: '100px 10px 10px 10px', // '0px'- deafult값
                threshold: 0, // '0' = deafult값
            }
            const callback = (entries, observer) => {
           		entries.forEach(entry) => {
                	if(entry.isIntersecting) {
                    	entry.target.classList.add("active");
                    } else {
                    	entry.target.classList.remove("active");
                    }
                })
            }
            const observer = new IntersectionObserver(callback, options);
            boxes.forEach(box => observer.observe(box));
        </script>
    </body>
</html>

IntersectionObserver()에서 등록한 콜백함수의 인자에 entries, observer을 넣어 원하는 정보를 얻을 수 있다. entries를 살펴보면 배열 안에 IntersectionObserverEntry를 볼 수 있는데 이것은 화면에 들어온 요소의 정보를 담고 있다. 이 오브젝트를 다시 들여다보면 프로퍼티들을 확인할 수 있는데,

  • boundingClientRect: 요소의 좌표, 너비와 높이를 알 수 있다.
  • intersectionRatio: 얼마만큼 뷰포트 안에 들어왔는지 알 수 있다. (반 정도 들어와 있으면 0.5로 표시됨)
  • intersectionRect: 들어온 요소의 포지션과 크기의 정보를 알 수 있다.
  • isIntersecting: 요소가 안으로 들어온 상태라면 true, 요소가 밖으로 나가면 false
  • isVisible: 현재 요소가 보여지는지 아닌지 알 수 있다.
  • rootBounds: 현재 계산하는 부모요소의 좌표, 너비, 높이를 알 수 있다.
  • target: 지금 관찰하고 있는 요소를 확인.

여러 정보를 알 수 있다.

그래서 저 정보들을 바탕으로 entry.isIntersecting가 true일 때, 즉 요소가 안에 들어온 상태라면 active 클래스가 붙어서 보라색으로 박스색깔이 변한다.

그리고 옵션도 설정 할 수 있다. (options)

  • root: null이 deafult값(뷰포트)이고, 설정하고 싶으면 javascript의 선택자 쓰듯 쓰면 된다.
    ex) root: document.querySelector(".container");
  • rootMargin: 0px이 deafult값이고, 설정한 크기만큼 뷰포트의 영역을 넓히는 것이다. 이미지를 먼저 다운로드하거나 필요한 컨텐츠를 미리 준비해둘 때 유용하게 사용할 수 있다. 마진은 css처럼 시계방향으로 넣어줄 수 있다.
  • threshold: 0이deafult값이고, 얼마만큼 보여줘야 콜백함수가 호출되는지를 설정할 수 있다. 전체 다 들어와야 콜백이 실행되게 하려면 1, 절반이 들어오면 콜백이 실행되게 하려면 0.5 이렇게 사용할 수 있는데 뷰포트에 들어올떄와 나갈때는 다르다. 예를 들어서 0.2로 threshold를 설정하면 요소의 20%가 뷰포트에 들어오면 콜백을 실행하고 다시 요소의 80%만큼 뷰포트에서 나가야 콜백함수가 다시 실행된다.

출처
드림코딩아카데미 포트폴리오웹사이트클론코딩을 보고 정리

profile
프론트엔드개발자가 되고 싶어서 열심히 땅굴 파는 자

0개의 댓글