今天的功能是當往下滾動頁面,會在對應的地方顯示圖片。
首先,獲取全部圖片,並將視窗增加滾動事件。
而作者有寫一個debounce的函數,我們將滾動的事件函數當作參數放進debounce,用意在下一段說明。
// 獲取全部圖片
let images = document.querySelectorAll('.site-wrap img');
// 滾軸滾動會觸發(連續)
// 將滾動函數作為參數包進debounce裡
window.addEventListener('scroll', debounce(scrollHandler));
由於滾動事件會連續觸發,會影響效能,所以我們可以利用debounce,去設定每個事件觸發之間的間隔,讓其不會連續觸發。
// func為我們要操作的函數,wait為延遲時間,immediate為第一次是否要立即執行
function debounce(func, wait = 20, immediate = true) {
var timeout;
return function () {
var context = this,
// 能獲取所有參數並以陣列型式返回
args = arguments;
var later = function () {
timeout = null;
// apply與call功能一樣差別在於傳遞參數方式
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
在滾動函數部分,首先我們要獲取當前視窗頂部的y座標,利用window.scrollY即可獲取
,反之底部y座標則是在當前頂部的地方,再加上當前視窗的高度(window.innerHeight)
。
而在來就是使圖片顯示。
第一個為只要圖片的頭部觸碰到視窗的底線,就會顯示圖片,而我們需要利用offsetTop去獲取圖片離頂部的高度
,當其高度小於底部就會顯示圖片。
第二個為只要圖片的中間觸碰到視窗的底線,這也是這此次我們所選擇的,而大多時候也是採用在中間的做法,會使User有更加的體驗,而我們除了需要利用offsetTop去獲取圖片離頂部的高度
,還要加上圖片本身一半的高度(Height/2),這樣就可獲取圖片中間距離底部的距離,當其高度小於底部就會顯示圖片。
第三個為只要圖片的底部觸碰到視窗的底線,就會顯示圖片,與第二個不同的在於不用除以2,而是要加上圖片本身的高度(Height),這樣就可獲取圖片底部距離底部的距離,當其高度小於底部就會顯示圖片。
function scrollHandler() {
// 視窗頂部y座標(也就是視窗的最上面的線)
let windowTop = window.scrollY;
// 視窗底部y座標(也就是視窗的最下面的線)
let windowBottom = windowTop + window.innerHeight;
console.log(windowTop, windowBottom);
// 讓圖片active
// 1.只要圖片頭部進到畫面(超過底線)就進來
// images.forEach((img) => {
// offsetTop為圖片離頂部的距離
// if (img.offsetTop < windowBottom) {
// img.classList.add('active');
// }
// });
// 2.只要圖片中間進到畫面(超過底線)就進來,一般都是用中間
images.forEach((img) => {
let imgMiddle = img.offsetTop + img.height / 2;
// offsetTop再加上圖片一半的高度
// 做優化(圖片中間位置要小於視窗底部且大於視窗頂部)
if (imgMiddle < windowBottom && imgMiddle > windowTop) {
img.classList.add('active');
} else {
img.classList.remove('active');
}
});
// 3.只要圖片尾部進到畫面(超過底線)就進來
// images.forEach((img) => {
// // offsetTop再加上圖片本身高度
// if (img.offsetTop + img.height < windowBottom) {
// img.classList.add('active');
// }
// });
}