이 글은 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.scrollY
window.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));