JavaScript

[ Javascript ] Intersection Observer 가지고 놀기

duqrlcks 2022. 8. 16. 23:42
반응형

공부하면서 Intersection Observer API의 활용 가능성이 참 많다는 것을 느꼈다. 그래서 이것저것 따라 만들어본 것을 기록하고자 이 글을 쓰게 됐다. 토스 홈페이지를 일부 참고했다.

 

구현을 완료하고나서 적는건데 내 생각대로 잘 안됐다. 스크롤 이벤트를 완전히 대체할 수 있겠다 싶었는데 한계가 있는 부분이 존재한다. 이에 대해서는 두 번째 섹션에서 언급하겠다. 

 

컨텐츠 따로 띄우기

토스 홈페이지

 

우선 초간단 예시를 먼저 구현해보자. 제목을 뭐라고 적어야할지 고민하다가 마땅한게 생각나지 않아서 아무렇게나 적었다. 컨텐츠를 포함하는 컨테이너 박스가 뷰포트에 노출되면 위처럼 효과가 작동한다. 따라서 단순히 observer에 컨테이너를 등록해주고, 각 요소에 transition을 정의한 클래스를 추가해주기만 하면 될 것 같다.

 

디자인은 저렇게까지 하지는 않고, 간단한 텍스트로 대체하겠다. 네 개의 컨텐츠가 동시에 올라오는게 아니라 약간 시간차를 두고 올라오는 것에 유의하면서 구현해보자. 그냥 transition delay만 다르게 주면 될 것 같다. 나는 0.7초의 간격을 줬다.

 

See the Pen Untitled by 이찬 (@vexkruqa-the-typescripter) on CodePen.

 

구현은 쉽다. 두 개의 transition class를 만들어주고, 교차하기 시작할때 첫번째, 네번째 컨텐츠와 두번째, 세번째 컨텐츠에 각각 class를 추가해주면 된다. 탐지가 끝나면 observer가 더이상 주시할 필요가 없기 때문에 disconnect로 끊어준다.

 

opacity 조절

 

entry의 속성 중에 intersectionRatio라는 값을 잘 활용하면 이쁜 UI를 만들 수 있다. 구현 자체는 굉장히 쉽다. 그냥 ratio 값을 opacity에 적용만 시켜주면 된다. 이번에는 그냥 이미지 태그에 바로 observer를 등록해주면 될 것 같다. 

 

쉬울줄 알았는데.... 내가 간과하고 있었던 부분이 있다. 원래 생각은 intersectionRatio를 그대로 opacity에 넣어줄 생각이었다. 그런데 observer가 트리거 되는게 뷰포트에 보이기 시작할 때도 해당되지만 뷰포트에서 나갈때도 해당된다. 즉, 이미지가 온전히 뷰포트에 다 보일때만 opacity가 1이 되고, 나머지 경우에는 1보다 작게 된다. 그리고 뷰포트의 높이가 이미지 높이보다 작으면 opacity가 1이 될 수 없다. 그래서 이 예제의 경우 어쩔 수 없이 scroll 이벤트를 써야 할 것 같다. 우선 내 지식 수준으로는 그렇다. 그래도 반쯤 성공한 구현 결과물은 아래와 같다. 몇시간의 삽질이 녹아있으나 결국 실패해서 결과 자체는 단순하다. 

 

See the Pen Untitled by 이찬 (@vexkruqa-the-typescripter) on CodePen.

 

 

원래 이미지 크기를 조절하는 예제까지 다뤄볼 생각이었지만 opacity가 해결되지 않는한 똑같은 문제에 봉착하는 것을 잘 알기에... 아쉽지만 여기까지다. 비록 삽질 시간이 많았지만 Intersection Observer API에 대해 약간은 알게된 거 같아서 의미있는 시간이었다. 

 

정리

특정 요소가 뷰포트에 등장할때 원하는 애니메이션 또는 트렌지션을 적용하고 싶으면 Intersection Observer가 아주 훌륭한 해결책이 될 수 있다.

 

'fade out 관찰자'로 예를 들어 보자. 특정 element가 뷰포트에 등장하면 fade out 효과를 주고 싶다면 intersection observer 객체를 하나 생성하고, 적용하고자 하는 요소들을 observe 메서드로 등록하면 된다. 그리고 isIntersecting 속성값을 활용해서 요소가 뷰포트에 등장할때 애니메이션 또는 트렌지션을 적용해주면 된다.

 

아래는 흔들리는 애니메이션을 적용시키는 oberserver를 하나 생성하고, 모든 박스를 관찰하도록 한 예시다. 모든 박스는 뷰포트에 등장하면 shake 애니메이션이 실행된다. 만약에 딱 한번만 실행시키고 싶다면 remove를 안해주면 된다. 또는 else 문을 지우고, add 밑에 observe.unobserve(entry.target) 을 추가하면 된다. 

 

See the Pen Untitled by 이찬 (@vexkruqa-the-typescripter) on CodePen.

 

 

반응형