可以试试点击后方使用交叉点观察期延迟加载图像以提高性能链接阅读体验会更好
前言
在自己平时浏览一些大量图片类的网站时,你会发现无论是你pc端下拉滚动条,还是移动端手动滑屏时,最终呈现的图片有时候会有所延迟,这是一种预先加载图片资源的方式,也就是俗称懒加载,实现该效果,通常有两种方式,分别是线性式(下拉窗帘式的)和渐进式(拨开晨雾见日明)图片加载,
至于前者这里暂且不谈,本文主要是介绍后者,在本文中主要给img标签添加一data-src属性(实际图片URL),以及src属性(存储相同图像的非常小的分辨率路径图片),在加载图片时,给用户过度从模糊淡入到图片清晰.当然更重要的是其中的js处理.如果文有误导的地方,欢迎路过的老师多提意见和指正
图片占据了你网站大小的较高比例。其中一些图像位于下方,这意味着网站访问者不会立即看到你的网站。他们需要向下滚动才能查看图像。如果你只能显示立即查看的图像,然后预先加载折叠下的图像呢?是的你可以。这就是这篇文章的内容。某处你必须看到这样的功能在Medium上
考虑图像源
我们将在这篇文章中考虑的例子将包含5张或更多图片,但每个图片都会有这种结构
目录
- 考虑图像源(data-src,与src)
- 观察员(创建实例并使用此实例观察DOM元素)
- 处理交叉路口(条目存储所有匹配的DOM元素,调用loadImage获取图像,然后适当地设置图像的src)
- 其他考虑事项(模糊转换为清晰时,为图像添加淡入效果)
- 结论(使用渐进式图片,你可以减少用户资源浪费大量时间来下载内容)
代码:
<img src="http://res.cloudinary.com/christekh/image/upload/c_scale,h_3,w_5/v1505391130/wynand-van-poortvliet-364366_gsvyby.jpg" data-src="http://res.cloudinary.com/christekh/image/upload/c_scale,h_300,w_500/v1505391130/wynand-van-poortvliet-364366_gsvyby.jpg" >
每个标签都有一个data-src和一个src属性
-
data-src
是我们希望读者看到的图像的实际URL(宽度:500px) -
src
包含相同图像的非常小的分辨率(宽度:5px)。这个分辨率将被拉伸以填充空间并且在真实图像加载时给访问者模糊的效果。较小的图像比其小10倍,所以如果所有条件都正常,则会加载速度更快(10倍)
这些图像存储在Cloudinary服务器上,可以通过URL(h_300,w_500或h_3,w_5)轻松调整图像的尺寸
这是完整的HTML代码示例
<div class="container">
<!-- Image 1 -->
<img src="" data-src="" alt="">
<!-- Image 2 -->
<img src="" data-src="" alt="">
<!-- Image 3 -->
<img src="" data-src="" alt="">
<!-- Image 4 -->
<img src="" data-src="" alt="">
<!-- Image 5 -->
<img src="" data-src="" alt="">
</div>
观察员
这是完整的js代码:
/**
*
* @authors 随笔川迹 (itclanCode@163.com)
* @date 2018-03-19 00:58:29
* @version $Id$
* @weChatPublicId ((itclanCoder))
* @QQGroup ((643468880))
* @PersonWeChatId ((suibichuanji))
* @PersonQQ ((1046678249))
* @link ((https://juejin.im/post/5a005392518825295f5d53c8))
* @describe 使用交叉点观察器延迟加载图像以提高性能js代码
*/
// 获取img标签元素
const images = document.querySelectorAll('img');
// 选项options
const options = {
// 如果图像在Y轴上达到50像素以内,请开始下载 If the image gets within 50px in the Y axis, start the download.
root: null, // 以页面作为根元素 Page as root
rootMargin: '0px',
threshold: 0.1
};
// 取得图片
const fetchImage = (url) => {
console.log(url);
return new Promise((resolve, reject) => {
const image = new Image();
image.src = url;
image.onload = resolve;
image.onerror = reject;
});
}
// 加载图片
const loadImage = (image) => {
const src = image.dataset.src;
fetchImage(src).then(() => {
// console.log(src)
image.src = src;
})
}
// 处理交叉路口,entries代表条目,observer观察者
const handleIntersection = (entries, observer) => {
entries.forEach(entry => {
if(entry.intersectionRatio > 0) {
console.log(entry.intersectionRatio);
loadImage(entry.target)
}
})
}
// 页面上图像的观察者 The observer for the images on the page
const observer = new IntersectionObserver(handleIntersection, options);
images.forEach(img => {
observer.observe(img);
})
观察者是交集观察者的一个实例。你创建实例并使用此实例观察DOM元素。你可以观察元素何时进入视口
const options = {
rootMargin:'0px',
threshold:0.1
}
const observer = new IntersectionObserver(handleIntersection,options);
该实例需要一个处理程序和一个选项参数。处理程序是当匹配交叉点发生时调用的函数,而options参数定义了观察者的行为。在这种情况下,我们希望处理器在图像进入视口后立即被调用(阈值:0.1)
你可以使用观察者观察页面中的所有图像
const images = document.querySelectorAll('img');
images.forEach(img => {
observer.observe(img);
})
处理交叉路口
我们为处理程序使用了一个方法,但没有定义它。这将会像预期的那样尖叫一个错误。让我们在实例上创建处理程序
const handleIntersection = (entries,observer) =>{
entries.forEach(entry =>{
if(entry.intersectionRatio > 0){
loadImage(entry.target);
}
}
)
}
该方法由带有条目数组和观察者实例的API调用。条目存储所有匹配的DOM元素(在这种情况下为imgs)的一个实例。如果匹配,我们用元素调用loadImage
loadImage获取图像,然后适当地设置图像的src
const loadImage = (image) => {
const src = image.dataset.src;
fetchImage(src).then(() => {
image.src = src;
})
}
它通过使用data-src值调用fetchImage方法来完成此操作。当实际图像返回时,它会设置image.src的值
fetchImage获取图像并返回一个承诺
const fetchImage = (url) => {
return new Promise((resolve,reject) => {
const image = new Image();
img.src = url;
image.onload = resolve;
image.onerror = reject;
})
}
其他考虑事项
考虑到流畅的用户体验,当从模糊转换为清晰时,你还可以为图像添加淡入效果。如果观看者认为加载时间较慢,这使得它更吸引眼睛
请注意,Intersection Observer在所有浏览器中都不被广泛支持,因此你可能会考虑使用填充或在页面加载后自动加载图像
if('IntersectionObserver' in window){
// observer code
const observer = new IntersectionObserver(handleIntersection,options);
}else{
Array.from(images).forEach(image => loadImage(image))
}
结论
使用渐进式图片,你可以减少用户资源浪费大量时间来下载内容,其实也就是预先加载资源更小的资源,策略就是减少文件的体积,循序渐进的加载,减少带宽,从而提高页面的访问速度,这在面试当中不妨也是一种优化页面性能的答复,当然还有其他?若知后文,关注微信itclanCoder公众号即可,下一篇内容继续揭晓...