
진~~~짜 유용하게 잘 쓰일 것 같은 챕터다.
스크롤을 내리면 비어있던 이미지들이 위치에 맞게 슬라이드 인 되는 기능이다.
🤔 그동안은 클릭이나 키다운에 의한 이벤트 함수를 생성했었는데,
이번 챕터에서는 스크롤한 위치에 따른 기능실행이라는 점이 신선했던 것 같다.
로직
- const
 
- eventListener + 함수생성
 
- offset값을 활용한 위치값 불러오기
 
const!
1
   | const slideIn = document.querySelectorAll('.slide-in');
  | 
 
이벤트리스너와 함수
1 2 3 4 5
   | function slide(e) {   console.log(e); }
  window.addEventListener('scroll', slide);
  | 
 

하지만, 이렇게 둘 경우 너무 자주 함수(slide)가 실행되어 비효율적일 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
   | 
  function debounce(func, wait = 10, immediate = true) {   var timeout;   return function () {     var context = this,       args = arguments;     var later = function () {       timeout = null;       if (!immediate) func.apply(context, args);     };     var callNow = immediate && !timeout;     clearTimeout(timeout);     timeout = setTimeout(later, wait);     if (callNow) func.apply(context, args);   }; }
 
  window.addEventListener('scroll', debounce(slide));
 
  | 
 
offset 값을 활용!
💡 scrollY : 세로로 스크롤이 몇 px만큼 움직였는지 알 수 있음
💡 innerHeight : 현재 뷰포트의 세로값(px)을 알 수 있음
어느 위치를 기준으로 이미지가 슬라이드 인 되어야 할까?

🤔 이미지의 세로 중간 쯤 뷰포트 바텀라인이 도착하면 슬라이드인 되도록 하는 것이 자연스러울 것 같다.
💡 그럼 ! 일단 현재 얼마나 스크롤 됐는지에 대한 값을 불러오는 변수를 설정해주자.
얼마나 스크롤 됐는지?
❗ 뷰포트 바닥을 기준으로 계산을 할 것이다. (상단 기준이면 scrollY만 있어도 됨)
1 2 3
   |  const slideAt = window.scrollY + window.innerHeight; console.log(slideAt);
 
  | 
 
이미지의 바닥 위치
1 2
   |  const imageBottom = slideImage.offsetTop + slideImage.height;
 
  | 
 
offsetTop?
💡 부모의 상단 보더로부터 자신의 상단 보더가 떨어진 만큼의 거리!

슬라이드인 조건들
스크롤이 이미지의 절반까지 위치했는가?
1
   | const isHalfShown = slideAt > slideImage.offsetTop + slideImage.height / 2;
   | 
 
화면에서 이미지가 이미 지나쳐갔는가?
1 2
   |  const isPassed = window.scrollY < imageBottom;
 
  | 
 
이제 이미지를 위의 두 조건이 아닐 경우에는 이미지가 슬라이드 아웃 되도록 해주면 된다.
최종 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
   | function debounce(func, wait = 10, immediate = true) {   var timeout;   return function () {     var context = this,       args = arguments;     var later = function () {       timeout = null;       if (!immediate) func.apply(context, args);     };     var callNow = immediate && !timeout;     clearTimeout(timeout);     timeout = setTimeout(later, wait);     if (callNow) func.apply(context, args);   }; }
  const slideIn = document.querySelectorAll('.slide-in');
  function slide(e) {   slideIn.forEach((slideImage) => {     const slideAt = window.scrollY + window.innerHeight;     console.log(slideAt);     console.dir(slideImage);          const imageBottom = slideImage.offsetTop + slideImage.height;     const isHalfShown = slideAt > slideImage.offsetTop + slideImage.height / 2;     const isPassed = window.scrollY < imageBottom;     if (isHalfShown && isPassed) {       slideImage.classList.add('active');     } else {       slideImage.classList.remove('active');     }   }); }
  window.addEventListener('scroll', debounce(slide));
  |