Skip to main content

[JS30] Day13: Slide In on Scroll

這堂課教我們滑鼠滾動事件(scroll)的應用,隨著滑動圖片會出現,離開時圖片消失。主要是學習了 window 物件和 debounce(延遲)函式的應用。

CSS

在要滑入的圖片加入.active 的 class 會滑入,透過translateX,opacity達成

.slide-in {
opacity: 0;
transition: all 0.5s;
}

.align-left.slide-in {
transform: translateX(-30%) scale(0.95);
}

.align-right.slide-in {
transform: translateX(30%) scale(0.95);
}

.slide-in.active {
opacity: 1;
transform: translateX(0%) scale(1);
}

JavaScript

debouce 函式會使得帶入的 func 先呼叫一次,之後隔 20 毫秒再次呼叫,因為 scroll 事件發生太快,所以需要用 debouce 來延遲函式的呼叫。

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);
};
}

window.scrollY 為螢幕滑過的 pixel,window.innerHeight 為螢幕高度,兩者加起來要大過於 sliderImage 的一半位置,才會設 isHalfShown 為真(這邊是 scrollY 加上 innerHeight 往回先剪去圖片的一半高度大於圖片的頂端 offsetTop,實際上是一樣)。而當 window.scrollY < imageBottom 就表示圖片還在螢幕中。圖片滑到一半跟圖片仍在螢幕都要加入.active 的 class。

const sliderImages = document.querySelectorAll(".slide-in");

function checkSlide(e) {
sliderImages.forEach((sliderImage) => {
// half way through the image
const slideInAt =
window.scrollY + window.innerHeight - sliderImage.height / 2;
// bottom of the image
const imageBottom = sliderImage.offsetTop + sliderImage.height;
const isHalfShown = slideInAt > sliderImage.offsetTop;
const isNotScrolledPast = window.scrollY < imageBottom;
if (isHalfShown && isNotScrolledPast) {
sliderImage.classList.add("active");
} else {
sliderImage.classList.remove("active");
}
});
}

window.addEventListener("scroll", debounce(checkSlide));