首屏加载速度优化——图片懒加载
什么是懒加载
懒加载其实就是延迟加载,是一种对网页性能优化的方式,比如当访问一个页面的时候,优先显示可视区域的图片而不一次性加载所有图片,当需要显示的时候再发送图片请求,避免打开网页时加载过多资源。
原理
<img>标签有一个属性是src,用来表示图像的URL,当这个属性的值不为空时,浏览器就会根据这个值发送请求。如果没有src属性,就不会发送请求。我们先不给<img>设置src,把图片真正的URL放在另一个属性data-src中,在需要的时候也就是图片进入可视区域的之前,将URL取出放到src中。
实现
html结构
<div class="container">
<div class="img-area">
<img class="my-photo" alt="loading" data-src="./img/img1.png">
</div>
<div class="img-area">
<img class="my-photo" alt="loading" data-src="./img/img2.png">
</div>
<div class="img-area">
<img class="my-photo" alt="loading" data-src="./img/img3.png">
</div>
<div class="img-area">
<img class="my-photo" alt="loading" data-src="./img/img4.png">
</div>
<div class="img-area">
<img class="my-photo" alt="loading" data-src="./img/img5.png">
</div>
</div>
仔细观察一下,<img>标签此时是没有src属性的,只有alt和data-src属性。
alt属性是一个必需的属性,它规定在图像无法显示时的替代文本。
data-* 全局属性:构成一类名称为自定义数据属性的属性,可以通过HTMLElement.dataset来访问。
如何判断元素是否在可视区域
方法一
① 通过document.documentElement.clientHeight获取屏幕可视窗口高度
② 通过element.offsetTop获取元素相对于文档顶部的距离
③ 通过document.documentElement.scrollTop获取浏览器窗口顶部与文档顶部之间的距离,也就是滚动条滚动的距离
然后判断③-②<①是否成立,如果成立,元素就在可视区域内。
方法二
通过getBoundingClientRect()方法来获取元素的大小以及位置:这个方法返回一个名为ClientRect的DOMRect对象,包含了top、right、botton、left、width、height这些值。
假设const bound = el.getBoundingClientRect();来表示图片到可视区域顶部距离;
并设 const clientHeight = window.innerHeight;来表示可视区域的高度。
随着滚动条的向下滚动,bound.top会越来越小,也就是图片到可视区域顶部的距离越来越小,当bound.top===clientHeight时,图片的上沿应该是位于可视区域下沿的位置的临界点,再滚动一点点,图片就会进入可视区域。也就是说,在bound.top<=clientHeight时,图片是在可视区域内的。
function isInSight(el) {
const bound = el.getBoundingClientRect();
const clientHeight = window.innerHeight;
//如果只考虑向下滚动加载
//const clientWidth = window.innerWeight;
return bound.top <= clientHeight + 100; // +100是为了提前加载。
}
页面打开时需要对所有图片进行检查,是否在可视区域内,如果是就加载。
function checkImgs() {
const imgs = document.querySelectorAll('.my-photo');
Array.from(imgs).forEach(el => {
if (isInSight(el)) {
loadImg(el);
}
})
}
function loadImg(el) {
if (!el.src) {
const source = el.dataset.src;
el.src = source;
}
}
JQ实现懒加载
有一款jquery的lazyload插件可以实现图片延迟加载的插件。依赖JQuery引入lazyload.js,对我们想要延迟加载的图片添加lazy样式,用"data-original"替换图片的引用路径。
<!-- 对img标签使用 -->
<img class="lazy" data-original="img/example.jpg">
<!-- 延迟加载元素的背景图 -->
<div class="lazy" data-original="img/bg.jpg">
...
</div>
在JS文件中调用lazyload()方法
$().ready(function(){
//可任意选择你想延迟加载的目标元素,例如直接使用样式名lazy作为选择条件
$("img .lazy").lazyload({
placeholder : "img/grey.gif", //占位图
effect: "fadeIn", // 加载效果
threshold: 200, // 提前加载
event: 'click', // trigger
container: $("#container"), //指定容器
failurelimit : 5 // 发生混乱时的hack手段
})
})
placeholder:占位图片,图片路径值,图片加载时占位图自动隐藏;
effect:图片载入时动画效果,值有show(直接显示),fadeIn(淡入),slideDown(滑入)等jq常用效果;
threshold:提前开始加载高度;数字值,是离需要加载目标的高度。如设置为200,表示滚动条在离目标位置还有200的高度时就开始加载图片,避免用户看到图片加载过程;
event:图片加载trigger;值有click(点击),mouseover(鼠标划过),sporty(运动的),foobar(…);
container:指定容器;lazyload默认在滚动浏览器滚动条时生效,这个参数可以让你在滚动某DIV的滚动条时执行懒加载;
failurelimit:提高稳定性,若是某一张该被加载的图片未能正确加载,则加载其后的第N张图;