Intersection Observer API

Geonil Jang·2021년 1월 9일
0
post-thumbnail
post-custom-banner

비동기적인 요소의 인터섹션을 감지한다.

  • 현재 스크롤 하면서 화면에 보여지는 요소 찾기
  • 인피니티 스크롤만들기
  • 이미지/ 데이터 프리패칭 하기 좋은 api라고 생각
  • MDA Intersection Observer API
//intersection Observer api

const boxes = document.querySelector(".box") // 감지를 하기 위한 엘레 먼트를 준비한다.
const observer = new IntersectionObserver((entries, observer) => {
  console.log(entries) //화면에 들어온 요소의 정보를 가지고 있습니다.
  //boundingClientRect => browser기분으로 좌측 상당의 좌표를 알아 낼 수 있습니다.
  //초과 하면 마이너스
  //intersectionRation 0 -> 1 로 들어온 비율을 알 수 있다.
  //isIntersecting -> 안으로 들어 오는 상태면 true / 나가는 상태면 false
  //rootBounds -> window 크기를 알아 낼 수 있어요.
  entries.forEach(entry=>{
  	console.log(entry.target);
    if(entry.isIntersecting){
      //들어오는 상태
      entry.target.classList.add('active')
    }else{
      //나가는 상태를 알 수 있어요
      entry.target.classList.remove('active')
    }
  })
  
  console.log(observer) 
  
}, {
//세부적인 옵션을 적용할 수 있어요.
  root:null, // default null / viewport
  // document.querySelector(container target) 으로 해주면 됩니다. 
  rootMargin:0, // 계산의 영역을 조금 넓게 설정 할 수 있다 viewport + margin 값으로 계산할 수 있어요. ex) 이미지 prefetching, infinitiscrolling data call
  threshold: 1, // 0~1 화면에 어느 정도에 들어 오게 되면 콜백을 호출할 것인지

}) // web api 특정 영역에서 콜백을 호출해준다.

boxes.forEach(box => observer.observer(box))// 관찰을 등록해 둔다.
//화면에 보이면 콜백이 호출됩니다.

예제

//css로 .active일 경우에 무엇을 할지를 정해줍니다.
//1. 모든 섹션 요소들과 메뉴 아이템을 가지오 온다.
const sectionIds = ["#home","#about","#skills","#testimonials","#contack"];
const sections = sectionIds.map(document.querySelector);
const navITems = sectionIds.map(id => document.querySelector(`[data-link=${id}]`));
let selectedNavIndex = 0;
let selectedNavItem = navItem[0]
const selectedItem = (selected) => {
	  selectedNavItem.classList.remove('active');
      selectedNavItem =  selected;
      selectedNavItem.classList.add('active');
}
//2. intersectionObserver를 이용해서 모든 섹션들을 가져온다.
const observerOptions = {
	root:null,
	rootMargin:'0px',
  	threshold:0.3
}
       
const observerCallback = (entries, observer)=> {

  entries.forEach(entry => {
  //3. 보여지는 센션에 해당하는 메뉴 아이템을 활성화 시킨다.
    console.log(entry.target);
    if(!entry.isIntersecting && entry.intersectionRation > 0){
    	//나갈때
		const index = sectionIds.indexOf(`#{entry.target.id}`);
      	if(entry.boundingClientRect.y < 0){//scroll up
        	selectedNavIndex = index + 1;
        }else{
        	selectedNavIndex = index - 1; // scroll down
        }
    }
    
  })
}
const observer = new IntersectionObserber(observerCallback,observerOptions)
sections.forEach(observer.observer)

//scroll <- 브라우저의 모든 스크롤
//wheel <- 사용자가 손으로 스크롤 하는 경우
window.addEventLisnter('wheel', ()=>{
  if(window.scrollY === 0){
    selecteedNavIndex = 0;
  }else if(Math.round(window.scrollY + window.innerHeight) >= document.body.clientHeight){
  	 selectedNabInde = navItems.length - 1;
  }
	selectedItem(navItems[selectedNavIndex])
})













profile
takeaways
post-custom-banner

0개의 댓글