成品連結:Custom Video Player、程式碼
今天的主題是常見的網站圖片動畫,也就是當滾動至圖片時圖片才會出現,且當圖片離開畫面時會再次隱藏。
透過今天的練習也會更了解 DOM 元素中的屬性操作~
從程式碼可以看到網頁中目前有 5 張圖片,而本次要做的事是當滾動至圖片一半的位置時顯示圖片;而當滾動離開圖片時隱藏圖片,顯示、隱藏的效果透過增加 / 去除 CSS class active
來達成。
這裡使用的事件是 scroll
,也就是當視窗滾動時觸發 callback function
window.addEventListener('scroll', checkSLide);
但如果你試著在頁面印出 console.count(e)
,就會發現從頭滾動到尾會觸發事件超果 100 次,而這可能會對電腦效能造成一定程度的負擔。因此,這裡我們導入 debounce(程式碼請見上方連結),目的是要控制事件觸發的頻率,也就是說至少要間隔一定的時間才會再次觸發事件。
原本的程式碼可以改成:
window.addEventListener('scroll', debounce(checkSLide));
首先先把所有圖片存入一個變數
const slideIns = document.querySelectorAll('img.slide-in');
接著開始寫 function 內容
function checkSLide(e) {
slideIns.forEach(img => {
// code here
});
}
重點來了,要如何偵測目前滾動(視窗底部)是否已到達圖片一半的位置了呢?
首先需要先知道目前滾動到了哪裡,而 window.scrollY
提供了滾動的距離;接著再加上 window.innerHeight
就是視窗底部的位置了。
const slideInAt = window.scrollY + window.innerHeight;
接著圖片中有個屬性 offsetTop
提供了該圖片至網頁頂端的距離(不是視窗喔!),所以當 slideInAt === img.offsetTop
時也就是當視窗底部位置與圖片上緣重疊了;但是由於我們的目的是當滾動至圖片一半時圖片才會出現,所以原本的 slideInAt
需要做一點小調整,也就是扣掉圖片一半的高度
const slideInAt = window.scrollY + window.innerHeight - (img.height / 2);
// 當滾動超過圖片一半時可以顯示圖片
const isImageShown = slideInAt > img.offsetTop;
當滾動至圖片一半時可以出現了,接下來要設定當圖片離開畫面時隱藏圖片,也就是說當滾動距離 >(圖片距離網頁頂端距離 + 圖片高度)時
這裡滾動距離不需要加上視窗高度,因為圖片離開會從視窗上緣離去
const imageBottom = img.offsetTop + img.height;
// 當(圖片距離網頁頂端距離 + 圖片高度)> 滾動距離時可以顯示圖片
const isNotScrollPast = window.scrollY < imageBottom;
綜合以上兩點寫入 checkSlide
function checkSLide(e) {
slideIns.forEach(img => {
const slideInAt = window.scrollY + window.innerHeight - (img.height / 2);
// 當滾動超過圖片一半時可以顯示圖片
const isImageShown = slideInAt > img.offsetTop;
const imageBottom = img.offsetTop + img.height;
// 當(圖片距離網頁頂端距離 + 圖片高度)> 滾動距離時可以顯示圖片
const isNotScrollPast = window.scrollY < imageBottom;
if (isImageShown && isNotScrollPast) {
img.classList.add('active');
} else {
img.classList.remove('active');
}
});
}
這樣就完成了。或許你會覺得很抽象,尤其是各種不同屬性的相加 / 減到底是怎麼發生的;可以試著印出上面有提到的屬性並試著畫出圖來作比較,或許會讓你更清楚一些。