이 글은 js30의 13강 Slide in on Scroll을 정리한 글입니다
window.addEventListener("scroll")이벤트로부터이미지의 절반 좌표위치와viewport 밑바닥 좌표위치를 얻은 다음, 둘의 좌표위치를 비교해 처리
window.addEventListener("scroll", checkslide);
window 인터페이스의 scroll event 는 스크롤을 하면 콜백함수 checkslide를 발생시킵니다
scroll event는 아주 미세한 스크롤에도 반응하기 때문에 debounce를 통해 과부화 및 리소스 낭비를 방지합니다
debounce를 적용해 수백번, 수천번의 스크롤 이벤트 요청에도 마지막의 이벤트 요청단 한번만이벤트 처리를 수행 할 수 있습니다
debounce 함수 코드에 대해서는 이 글에서 따로 설명하지 않습니다
debounce 적용
window.addEventListener("scroll", debounce(checkslide) );
이제부터 콜백함수 checkslide 함수를 정의하겠습니다
function checkslide(e){
....
....
}

document.body.clientHeight웹 페이지 body의 높이입니다
document.height는 권장되지 않습니다- by MDN
window.innerHeight브라우저의 현재 높이입니다 (viewport의 높이라고도 합니다)

window.scrollYwindow.pageYOffset과 똑같은 기능입니다scrollY는 IE9에서 지원하지 않습니다
scrollY + window.innerHeight는viewport의 가장 밑바닥절대 위치를 알려줍니다

image.offsetTop은 document.body로부터 떨어진 image 위치입니다
image 절반위치의 절대좌표는 image.offsetTop + image.height/2입니다
만약 viewport의 맨 밑바닥 좌표 > image 절반위치의 절대좌표라면
=> 이미지 절반 이상이 viewport에 보였다는 뜻이기 때문에 이미지가 나타나야 됩니다
isHalfShown라는 변수를 만들어 담아둡니다const viewportBottom = window.innerHeight + window.scrollY;
const imageHalfBottom = sliderImage.offsetTop + sliderImage.height / 2;
const isHalfShown = viewportBottom > imageHalfBottom;
스크롤한 뒤 image가 viewport에서 완전히 위로 사라졌다면(지나갔다면) 원래대로 숨겨줘야합니다
변수 isNotScrollPast를 두어 image가 viewport를 지나갔는지 판단합니다
const isNotScrollPast =
window.scrollY < sliderImage.offsetTop + sliderImage.height;
active한 상태를 판단합니다이미지 절반 이상이 노출됬고 and 아직 이미지가
viewport에 남아있다면 active 클래스를 추가합니다if (isHalfShown && isNotScrollPast) { sliderImage.classList.add("active"); } else { sliderImage.classList.remove("active"); }
active 상태면 opacity와 위치를 원래대로 되돌립니다
// 이미지 클래스 <image class="align-right(left) slide-in">
//최초 이미지는 투명 opacity:0
.slide-in {
opacity: 0;
transition: all 0.5s;
}
// 왼쪽, 오른쪽에 따라 이미지의 x좌표를 옮겨줍니다
.align-left.slide-in {
transform: translateX(-30%)
scale(0.95);
}
.align-right.slide-in {
transform: translateX(30%)
scale(0.95);
}
// active 상태면 원상복구합니다
.slide-in.active {
opacity: 1;
transform: translateX(0%)
scale(1);
}
function debounce(func, wait = 20, 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 sliderImages = document.querySelectorAll(".slide-in");
function checkSlide(e) {
sliderImages.forEach((sliderImage) => {
const viewportBottom = window.innerHeight + window.scrollY;
const imageHalfBottom =
sliderImage.offsetTop + sliderImage.height / 2;
const isHalfShown = viewportBottom > imageHalfBottom;
const isNotScrollPast =
window.scrollY < sliderImage.offsetTop + sliderImage.height;
if (isHalfShown && isNotScrollPast) {
sliderImage.classList.add("active");
} else {
sliderImage.classList.remove("active");
}
});
}
window.addEventListener("scroll", debounce(checkSlide));