当前位置:网站首页>图片延迟加载、预加载
图片延迟加载、预加载
2022-08-04 19:16:00 【Ares-Wang】
1、图片延迟加载 loading 属性
定义:延迟加载也称为惰性加载,即在长网页中延迟加载图像。用户滚动到它们之前,视口外的图像不会加载。这与图像预加载相反,在长网页上使用延迟加载将使网页加载更快。在某些情况下,它还可以帮助减少服务器负载。
举个例子来说明,当打开淘宝首页的时候,只有在浏览器窗口里的图片才会被加载,当你滚动首页向下滑的时候,进入视口内的图片才会被加载,而其它从未进入视口的图像不会也不会加载。
那么延迟加载有什么好处:
首先它能提升用户的体验,试想一下,如果打开页面的时候就将页面上所有的图片全部获取加载,如果图片数量较大,对于用户来说简直就是灾难,会出现卡顿现象,影响用户体验。
有选择性地请求图片,这样能明显减少了服务器的压力和流量,也能够减小浏览器的负担。
那么下面就介绍延迟加载的三种实现方式:
第一种:
首先将页面上的图片的 src 属性设为 loading.gif,而图片的真实路径则设置在 data-src 属性中,页面滚动的时候计算图片的位置与滚动的位置,当图片出现在浏览器视口内时,将图片的 src 属性设置为 data-src 的值,这样,就可以实现延迟加载。
下面是具体的实现代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Lazyload 1</title>
<style> img {
display: block; margin-bottom: 50px; height: 200px; } </style>
</head>
<body>
<img src="images/loading.gif" data-src="images/1.png">
<img src="images/loading.gif" data-src="images/2.png">
<img src="images/loading.gif" data-src="images/3.png">
<img src="images/loading.gif" data-src="images/4.png">
<img src="images/loading.gif" data-src="images/5.png">
<img src="images/loading.gif" data-src="images/6.png">
<img src="images/loading.gif" data-src="images/7.png">
<img src="images/loading.gif" data-src="images/8.png">
<img src="images/loading.gif" data-src="images/9.png">
<img src="images/loading.gif" data-src="images/10.png">
<img src="images/loading.gif" data-src="images/11.png">
<img src="images/loading.gif" data-src="images/12.png">
<script> function lazyload() {
var images = document.getElementsByTagName('img'); var len = images.length; var n = 0; //存储图片加载到的位置,避免每次都从第一张图片开始遍历 return function() {
var seeHeight = document.documentElement.clientHeight; var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; for(var i = n; i < len; i++) {
if(images[i].offsetTop < seeHeight + scrollTop) {
if(images[i].getAttribute('src') === 'images/loading.gif') {
images[i].src = images[i].getAttribute('data-src'); } n = n + 1; } } } } var loadImages = lazyload(); loadImages(); //初始化首页的页面图片 window.addEventListener('scroll', loadImages, false); </script>
</body>
</html>
比较 image 的 offsetTop 与 seeHeight + scrollTop 的大小,当小于时则说明图片已经出现过在视口中,这时候继续判断图片是否已经替换过,如果没有替换过,则进行替换。
实现的效果:不断滑动页面时,图片延迟加载
你可以拷贝我的代码去进行实验,但是请确保 HTML 同目录下有 images 目录并且含有 1~12.png 和 loading.gif。
需要提及的是变量 n 是用来保存已经加载的图片数量,避免每次都从第一张图片开始遍历,提升性能。上面的代码用到了 JS 闭包的知识,如果你不太熟悉的话,可以自行百度一下。
第二种:
上面的代码是没什么问题,但是性能偏差。如果直接将函数绑定在 scroll 事件上,当页面滚动时,函数会被高频触发,这非常影响浏览器的性能。我粗略地估计一下,当简单地滚动一下页面,函数至少触发了十来次,这显然是十分没必要的。
所以在做事件绑定的时候,可以对 lazyload 函数进行函数节流(throttle)与函数去抖(debounce)处理。
这里我并不再另外介绍这两种方案,如果你想了解的话可以阅读: JS魔法堂:函数节流(throttle)与函数去抖(debounce) -
Debounce:一部电梯停在某一个楼层,当有一个人进来后,20秒后自动关门,这20秒的等待期间,又一个人按了电梯进来,这20秒又重新计算,直到电梯关门那一刻才算是响应了事件。
Throttle:好比一台自动的饮料机,按拿铁按钮,在出饮料的过程中,不管按多少这个按钮,都不会连续出饮料,中间按钮的响应会被忽略,必须要等这一杯的容量全部出完之后,再按拿铁按钮才会出下一杯。
下面就是经过 throttle 处理后的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Lazyload 2</title>
<style> img {
display: block; margin-bottom: 50px; height: 200px; } </style>
</head>
<body>
<img src="images/loading.gif" data-src="images/1.png">
<img src="images/loading.gif" data-src="images/2.png">
<img src="images/loading.gif" data-src="images/3.png">
<img src="images/loading.gif" data-src="images/4.png">
<img src="images/loading.gif" data-src="images/5.png">
<img src="images/loading.gif" data-src="images/6.png">
<img src="images/loading.gif" data-src="images/7.png">
<img src="images/loading.gif" data-src="images/8.png">
<img src="images/loading.gif" data-src="images/9.png">
<img src="images/loading.gif" data-src="images/10.png">
<img src="images/loading.gif" data-src="images/11.png">
<img src="images/loading.gif" data-src="images/12.png">
<script> function throttle(fn, delay, atleast) {
var timeout = null, startTime = new Date(); return function() {
var curTime = new Date(); clearTimeout(timeout); if(curTime - startTime >= atleast) {
fn(); startTime = curTime; }else {
timeout = setTimeout(fn, delay); } } } function lazyload() {
var images = document.getElementsByTagName('img'); var len = images.length; var n = 0; //存储图片加载到的位置,避免每次都从第一张图片开始遍历 return function() {
var seeHeight = document.documentElement.clientHeight; var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; for(var i = n; i < len; i++) {
if(images[i].offsetTop < seeHeight + scrollTop) {
if(images[i].getAttribute('src') === 'images/loading.gif') {
images[i].src = images[i].getAttribute('data-src'); } n = n + 1; } } } } var loadImages = lazyload(); loadImages(); //初始化首页的页面图片 window.addEventListener('scroll', throttle(loadImages, 500, 1000), false); </script>
</body>
</html>
设置了 500ms 的延迟,和 1000ms 的间隔,当超过 1000ms 未触发该函数,则立即执行该函数,不然则延迟 500ms 执行该函数。
实现效果:可以看出有一定的延迟。
参考链接: 实现图片懒加载(lazyload)
第三种: 使用 IntersectionObserver API
目前有一个新的 IntersectionObserver API,可以自动"观察"元素是否可见,Chrome 51+ 已经支持。
这里不过多介绍 IntersectionObserver API 的详细使用,感兴趣可以另外阅读下面的文章:
IntersectionObserver API 使用教程
Intersection Observer API
实现代码:简洁,但是浏览器尚未全部实现。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Lazyload 3</title>
<style> img {
display: block; margin-bottom: 50px; width: 800px; } </style>
</head>
<body>
<img src="images/loading.gif" data-src="images/1.png">
<img src="images/loading.gif" data-src="images/2.png">
<img src="images/loading.gif" data-src="images/3.png">
<img src="images/loading.gif" data-src="images/4.png">
<img src="images/loading.gif" data-src="images/5.png">
<img src="images/loading.gif" data-src="images/6.png">
<img src="images/loading.gif" data-src="images/7.png">
<img src="images/loading.gif" data-src="images/8.png">
<img src="images/loading.gif" data-src="images/9.png">
<img src="images/loading.gif" data-src="images/10.png">
<img src="images/loading.gif" data-src="images/11.png">
<img src="images/loading.gif" data-src="images/12.png">
<script> function query(selector) {
return Array.from(document.querySelectorAll(selector)); } var io = new IntersectionObserver(function(items) {
items.forEach(function(item) {
var target = item.target; if(target.getAttribute('src') == 'images/loading.gif') {
target.src = target.getAttribute('data-src'); } }) }); query('img').forEach(function(item) {
io.observe(item); }); </script>
</body>
</html>
IntersectionObserver 传入一个回调函数,当其观察到元素集合出现时候,则会执行该函数。
io.observe 即要观察的元素,要一个个添加才可以。
io 管理的是一个数组,当元素出现或消失的时候,数组添加或删除该元素,并且执行该回调函数。
3 、Lozad.js
实现图像的延迟加载的一种快速简便的替代方法是让JS库为你完成大部分工作。
Lozad是纯JavaScript中的高性能,轻量且可配置的惰性加载器,没有任何依赖关系。你可以使用它来延迟加载图像,视频,iframe和更多内容,并且它使用Interp Observer API。
你可以将Lozad包含在npm / Yarn中,并使用所选的模块捆绑器将其导入:
npm install --save lozadyarn add lozad
import lozad from ‘lozad’;
另外,你可以简单地使用CDN下载该库并将其添加到HTML页面底部的< script>标记中:
接下来,对于基本实现,将lozad类添加到标记中的资产:
最后,在你的JS文档中实例化Lozad:const observer = lozad();observer.observe();
你将在Lozad GitHub存储库中找到有关如何使用该库的所有详细信息。
如果你不想深入了解Interp Observer API的工作原理,或者只是在寻找适用于各种内容类型的快速实现,则Lozad是一个不错的选择。
仅注意浏览器支持,并最终将此库与用于Interp Observer API的polyfill集成。
边栏推荐
猜你喜欢
随机推荐
WPF 多个 StylusPlugIn 的事件触发顺序
我的四周年创作纪念日
在线生成接口文档
VPC2187/8 current mode PWM controller 4-100VIN ultra-wide voltage startup, highly integrated power control chip recommended
EuROC 数据集格式及相关代码
[Distributed Advanced] Let's fill in those pits in Redis distributed locks.
前3名突然变了,揭秘 7 月编程语言最新排行榜
ros2订阅esp32发布的电池电压数据-补充
工业相机CCD与CMOS
【CCIG 2022】视觉大模型论坛
win10 uwp xaml 绑定接口
Kubernetes之list-watch机制
运力升级助力算力流转,中国数字经济的加速时刻
Orthodontic MIA micro-implant anchorage technology China 10th anniversary exchange meeting was held in Shenyang
JS 问号?妙用
按需视觉识别:愿景和初步方案
动手学深度学习_VggNet
译文推荐|Apache Pulsar 隔离系列(四):单集群隔离策略
机器学习之支持向量机实例,线性核函数 多项式核函数 RBF高斯核函数 sigmoid核函数
如何进行自动化测试?