今天的功能是当往下滚动页面,会在对应的地方显示图片。
首先,获取全部图片,并将视窗增加滚动事件。
而作者有写一个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'); // } // }); }