Intersection Observer를 이용하여 스크롤시 등장 모션 구현하기
저번 포스팅에서 window.scrollY와 element.offsetTop을 이용하여 스크롤 위치에따른 등장 모션을 구현하는 법을 다뤘었습니다.
그런데 이 방법은 너무 복잡하기도 하고, 여러 요소에 같은 모션을 적용한다 하더라도 각각 높이를 계산하여 따로 붙여하는 수고가 있었습니다.
오늘은 Intersection observer라는 웹 api를 사용하여 좀 더 확장성있고, 가독성 좋은 모션을 만들어 보도록 하겠습니다.
Intersection Observer란?
intersection observer는 해당 요소가 화면안에 들어왔는지 혹은 나갔는지를 감지하는 기능을 제공하는 web api입니다. 한마디로 요소의 가시성을 감지합니다.
이를 이용하면 요소가 화면에 들어왔을 때 모션을 줄 수 있죠. 이 외에도 무한스크롤 혹은 image lazy-loading과 같은 여러 기능들을 편리하게 만들 수 있습니다.
자세한 내용은 아래의 링크를 확인하시면 좋습니다. :)
https://developer.mozilla.org/ko/docs/Web/API/Intersection_Observer_API
Intersection observer는 사용할 수 있는 옵션들이 많이 있어서 처음 사용하면 조금 복잡할 수 있습니다. 코드를 보면서 필요한 것만 콕 찝어서 차근차근 사용방법을 알려드리도록 하겠습니다.
먼저 설명을 좀 할텐데, 설명이 어렵고 장황하다고 느낄 수 있습니다. 그냥 마지막 코드만 보고 그대로 따라 사용해도 무방하니 마음 편하게 쭉 훑어보세요.
Intersection Observer 만들기
IntersectionObserver()를 이용하면 새로운 intersection observer를 생성할 수 있습니다.
const observer = new IntersectionObserver(callback, options);
보시면 인자로 callback과 options를 넘겨주고 있습니다.
콜백 함수는 화면안에 감지할 요소가 들어오거나 나갔을 때 실행할 함수이고, options는 객체 형태로 observer 콜백이 호출되는 조건을 전달합니다.
options
콜백이 호출되는 조건. 즉, 어디서부터 요소가 화면에 들어온 것으로 할 건지 설정하는 객체입니다.
options중 우리가 모션을 만들 때 사용할 조건은 'rootMargin'과 'threshold' 딱 2가지 입니다.
rootMargin은 요소의 가시성을 감지할 영역의 크기를 조정한다고 생각하면 됩니다. 기본값은 0으로 +가 되면 뷰포트보다 감지할 영역이 넓어지고, -가 되면 뷰포트보다 감지할 영역이 작아집니다.
CSS의 margin 속성과 유사하게 "10px 20px 30px 40px" (각각 top, right, bottom, left)로 표기합니다.
* 주의점 : 단위는 px, % 둘 다 상관없지만, 반드시 단위를 써줘야합니다.
threshold는 감지할 요소의 가시성 퍼센티지를 나타냅니니다. 만일 50%만큼 요소가 보여졌을 때를 탐지하고 싶다면, 값을 0.5로 설정하면 됩니다. 기본값은 0이고, 최대값은 1입니다.
let options = {
rootMargin: '0px', // '0px 0px 0px 0px'과 같음
threshold: 0
}
callback
callback의 인자로 entries와 observer가 들어오는데 우리는 entries만 사용할겁니다. entries는 IntersectionObserverEntry 객체들의 배열이에요.
위의 말들 다 이해 안되도 상관 없고, 우리는 아래와 같은 형태의 callback을 사용할 것입니다.
let callback = (entries) => {
entries.forEach(entry => {
if(entry.isIntersecting){
// 모션 동작
}
});
};
여기서 isIntersecting은 감지대상이 교차영역에 진입했는지 판별한 boolean(true, false)값을 반환합니다.
Intersection observer에 감지할 요소 알려주기
const detectEl = document.getElementById('detect');
observer.observe(detectEl); // 감시할 요소 알려줄 땐 observe를 사용
감시 해제법은 다음과 같습니다.
observer.unobserve(detectEl); // 감시를 해제하고 싶을 땐 unobserve를 사용한다.
전체 형태
위의 설명이 이해안되도 아래의 코드를 그대로 사용하면 됩니다.
const detectEl = document.getElementById('detect');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) { // 감지대상이 교차영역에 진입 할 경우
// 모션
observer.unobserve(detectEl); // 한번 동작 후 감시 해제하고 싶을 때 사용
} else { // 감지대상이 교차영역에서 나간 경우
// 모션 전으로 초기화
}
});
}, {
rootMargin: '0% 0px 0%',
threshold: 0,
});
observer.observe(detectEl);
자 우린 이제 요소의 가시성을 감지할 수 있게 되었습니다. 모션을 한번 넣어볼까요?
classList로 클래스 이름을 추가하는 방법도 있지만 이번엔 js로 요소에 직접 스타일을 박는 방식을 써보겠습니다.
threshold를 0.5로 설정해서 요소의 절반이 보일 때 모션이 동작하도록 설정했습니다.
잘 동작하네요 :)
이해가 안되는 부분이 있다면 댓글 남겨주세요~
'결과물들' 카테고리의 다른 글
스크롤 시 등장 모션 만들기 - 순수 js (라이브러리x) (0) | 2022.01.25 |
---|---|
Canvas로 육각형 그래프 그리기 - js / vue (2) | 2021.12.13 |
Count up 효과 (숫자 올라가는 효과) - js / vue (0) | 2021.12.08 |
댓글