图片懒加载

背景:加载多张图片需要处理很多次网络请求,等待加载时间较长,用户体验感差。

 

解决方式:随着滚动动态加载,即图片的惰性加载。

优点:页面加载速度快,用户体验感好。

一、图片懒加载的原理

1.对于所有图片初始化为一个小尺寸的图片(非实际需要的图片),因为所有图片都用同一张图片初始化,只会发送一次请求。

2.将图片的真实路径存储在一个自定义属性中,如在HTML5中支持自定义属性命名data-xx。

3.当图片进入可视窗口,将img来源路径替换成真实的路径。

二、图片懒加载具体实现

2.1 初始化

1.设置lazy_image类用于设置默认加载图片,给所有img添加该类。

.lazy_image {
            background: url('./imgs/loading.gif') no-repeat center;
        }

2.初始化所有的img标签,将真实图片路径存于自定义属性data-image中。

<img data-src="./imgs/1.webp" class="lazy_image">

2.2 判断元素是否出现在可视窗口(目前只考虑垂直方向)

1.利用offsetTop、scrollTop等计算判别

用window.onscroll定义函数监听滚动

a.元素进入可视区

可见的条件:content.offsetTop + content.offsetHeight > scrollTop

b.元素即将离开可视区

可见的条件:content.offsetTop < scrollTop + content.offsetHeight

综上可见函数定义如下:

const isShow = function(ele){

return (ele.offsetTop + ele.offsetHeight > document.documentElement.scrollTop) && (ele.offsetTop < document.documentElement.scrollTop + ele.offsetHeight);

}

当元素部分或全部出现在视口范围内时,isShow()返回true。

2.利用getBoundingClientRect()

用window.onscroll定义函数监听滚动

使用element.getBoundingClientRect()返回一个对象,对象的属性包括元素的大小及其相对视口的位置。

其对象有属性left、right、top、bottom、height、width。

在这里插入图片描述

onst {top, buttom, left, right, height, width} = d1.getBoundingClientRect(); // 获取属性

综上可见函数定义如下:

const isShow = function (ele) {

const {top, buttom, left, right, height, width} = ele.getBoundingClientRect();

const showHeight = window.innerHeight || document.documentElement.clientHeight;

return (top >= -height) && (top <= showHeight);

}

当元素部分或全部出现在视口范围内时,isShow()返回true。

3.利用new IntersectionObserver(callback, options)

IntersectionObserver():重叠观察者,用于判定两个元素是否重叠,无需进行监听事件,可以自动“观察”元素是否可见,性能方面较getBoundingRect()会好很多。

IntersectionObserver API是异步触发,只有线程空闲才会执行观察期,优先级非常低。可以同时观察多个对象。

使用判定分为两个步骤:

1> 创建观察者 const observer = new IntersectionObserver(callback, options)

callback: 回调函数。

const callback = (entries, observer) => {

entries.forEach(entry => {

entry.time; // 触发的时间

entry.rootBounds; // 根元素的位置矩阵,一般视为窗口位置

entry.boundingClientRect; // 被观察者的位置矩阵

entry.intersectionRect; // 重叠区域的位置矩阵

entry.intersectionRatio; // 重叠区域占被观察者面积的比例 (被观察者不是矩阵时也按矩阵计算)

entry.target; // 被观察者

})

};

options: 配置触发相关属性。threshold: [,,,]决定什么时候触发回调函数;root:可选 定义监听对象的父元素;rootMargin:用于扩展或缩小rootBounds这个矩阵的大小,从而影响intersectionRect交叉区域的大小。使用CSS的定义方法,上右下左的顺序。这样设置后,不管是窗口滚动或者容器内滚动,只要被观察元素可见性发生变化,都会触发观察者。

2> 传入被观察者。通过observer.observe(target)来注册被观察者。

关于IntersectionObserver()其他方法:

1> 停止观察:observer.unobserve(element)

2> 关闭观察器:observer.disconnect()

综上可见性判定代码如下:

var target = document.querySelector('#target');
const options = {
     // 设置重叠面积占被观察者面积的比例 0~1
     threshold: [0, 0.25, 0.5, 0.75, 1], // 1表全部覆盖
};
// callback函数在重叠比例超过options中设置的threshold时会被执行
const callback = (entries, observer) => {
     entries.forEach(entry => {
          if (entry.intersectionRatio === 0) {
               // 不可见时操作代码
          }else{
               // 可见时操作代码
          }
})
};
const observer = new IntersectionObserver(callback, options);
observer.observe(target);

还可以通过entry.isIntersecting判定在视口中是否可见。entry.isIntersecting为true表示可见。

注意:针对需要srcoll事件监听协助的前两种方式,为防止事件重复触发,可以借助节流的方式减少触发频率。

2.3 获取img元素集合对于可见元素进行操作

判定可见时

1.获取特定元素data-src的值,用dataset.src获取。

2.将取到的真实图片路径赋值给img的src属性,去请求对应资源。

3.移除lazy_image类

具体实现可参考:图片懒加载 - 掘金

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值