整理图片延时加载技术,如何优雅的延时加载图片
#什么是延迟加载?
延迟加载是Web和应用程序开发中的一项技术,它们将页面上需要的但是暂时未使用的资源加载延迟到一定的时间点。延迟加载技术有助于提高性能,更好地利用设备资源并降低相关成本。
为什么使用延时加载?
显而易见的好处是我们可以更快地加载网页。延迟加载减少了需要预先在页面上加载的图像数量。较少的图像请求意味着下载的字节更少,页面呈现的速度比创建这些字节和请求的速度快。
第二个好处是降低对服务器传输资源的占用,页面上未使用的资源不做请求,降低成本
图像的延迟加载技术
图片通常使用img标签或者背景图片的方式加载入页面,我们先来看看img的方式
<img src="http://i1.bvimg.com/670529/44b708e57dc8c7e8.jpg"></img>
这是普通的加载图片方式,延时加载图片需要阻止它默认加载,于是我们这样写
<img data-src="https://ik.imagekit.io/demo/default-image.jpg" />
这种写法图片标签是不会加载图片的,于是我们需要告诉他什么时候加载这些图片
一般情况下我们判断,当该标签进入视口的时候,就是需要加载该图片的时候,我们有两种方式处理这个问题
1、使用Javascript事件触发图像加载
我们给每个需要延时加载的图片添加一个class :lazy,并对三个事件进行监控:
scroll: 屏幕滚动
resize: 浏览器尺寸改变
orientationChange: 移动端横竖屏
这三个事件不是一定的,根据需要选择
滚动时,滚动事件会快速触发多次。因此,为了提高性能,我们在脚本中添加了一个延时器,延时回调会异步执行,不会占用当前线程,多次调用清除定时器,最终只会产生一个加载回调
let lazyLoadImgs=document.querySelectorAll('img.lazy')//延时对象集
let timer=null //创建一个定时器对象
function lazyLoad(){
if(timer) clearTimeout(timer) //避免重复开启定时器
timer=setTimeout(function() {
let scrollTop=window.pageYOffset//屏幕滚动距离
for(let i=0,length=lazyLoadImgs.length;i<length;i++){
if(lazyLoadImgs[i].offsetTop<(window.innerHeight+scrollTop)){
lazyLoadImgs[i].src = img.dataset.src
lazyLoadImgs[i].classList.remove('lazy')
}
}
if(lazyLoadImgs.length===0){
document.removeEventListener("scroll", lazyload)
window.removeEventListener("resize", lazyload)
window.removeEventListener("orientationChange", lazyload)
}
},20)
}
document.addEventListener("scroll", lazyload)
window.addEventListener("resize", lazyload)
window.addEventListener("orientationChange", lazyload)
2、使用IntersectionObserver这个最新的交叉观察者API
交叉观察者API加载图像的速度要快得多,并且操作也会更快地触发
和所有的新API一样,交叉观察者API也是有兼容性问题的,ie浏览器和Safari并不支持
let lazyLoadImgs=document.querySelectorAll(img.lazy)//延时对象集
let imgObserver=new IntersectionObserver(function(items,observer){
for(let i=0,length=items.length;i<length;i++){
let item=items[i].target
item.src=item.dataset.src
item.classList.remove('lazy')
observer.unobserver(item)
}
})
for(let i=0,length=lazyLoadImgs.length;i<length;i++){
imgObserver.observer(lazyLoadImgs[i])
}
背景图片延时加载
背景图片延时加载与上面方法一样,只是我们通过css来控制,直接看代码
<div id="bg-img" class="lazy"></div>
#bg-img.lazy{
background-img:none;
}
#bg-img{
background-img:url('http://i1.bvimg.com/670529/44b708e57dc8c7e8.jpg');
background-repeat: no-repeat;
}
let lazyLoadImgs=document.querySelectorAll('.lazy')//延时对象集
let timer=null //创建一个定时器对象
function lazyLoad(){
if(timer) clearTimeout(timer) //避免重复开启定时器
timer=setTimeout(function() {
let scrollTop=window.pageYOffset//屏幕滚动距离
for(let i=0,length=lazyLoadImgs.length;i<length;i++){
if(lazyLoadImgs[i].offsetTop<(window.innerHeight+scrollTop)){
lazyLoadImgs[i].classList.remove('lazy')
}
}
if(lazyLoadImgs.length===0){
document.removeEventListener("scroll", lazyload)
window.removeEventListener("resize", lazyload)
window.removeEventListener("orientationChange", lazyload)
}
},20)
}
document.addEventListener("scroll", lazyload)
window.addEventListener("resize", lazyload)
window.addEventListener("orientationChange", lazyload)
更优雅的延时加载图片
延迟加载具有很好的性能优势,但是当网络很慢时肯能会让用户看到大量白框,而当用户快速下拉时,图片会明显延迟用户感知,会造成不好的体验。
于是我们使用更好的占位符来使加载过程更优雅,通过将图像缩小到1×1像素,然后将其放大到占位符的大小来实现这一目标
<img src="http://i1.bvimg.com/670529/44b708e57dc8c7e8.jpg?tr=w-1,h-1:w-400,h-300" data-src="http://i1.bvimg.com/670529/44b708e57dc8c7e8.jpg?tr=w-400,h-300"></img>
注意的问题1:提前定义图片大小,避免出现排版混乱
注意的问题2:稍微提前加载图片,提供更好体验