图片懒加载
为什么要图片懒加载
懒加载(按需加载)是一种对网页性能优化的方式。比如当访问一个页面的时候,优先显示可视区域的图片而不是一次性加载所有图片,当需要显示时,再发送图片请求,避免打开网页时加载过多资源。 懒加载就是页面需要显示图片的时候才进行加载,否则不加载。
当一个网站的加载图片过多时就需要懒加载的协助,页面图片多时,在首次载入时一次性加载会耗费时间长,使用懒加载可以使页面加载速度快、减轻服务器的压力、节省流量。
图片渲染的特殊性:
- 发送http请求先得到记录图片位置的字符串(src)
- image的src来发起请求,获取对应的图片放置到DOM树的这个位置上,从而实现图片的页面渲染。
图片懒加载的实现原理:图片的src按需发起请求,获取图片。
- 使用 html5 提供的自定义属性:data-xxx 存储图片地址。
- 使用 src 进行占位:每个照片都是相同的 src,当页面有多张重复图片时,只会发起一次请求。
- 判断图片是否在屏幕上:元素到屏幕顶部的距离小于屏幕高度时,就可以判定图片进入了屏幕。就把图片地址赋值给src,从而发起请求获取图片。
DOMobj.getBoundingClientRect().top //获取该元素到屏幕顶部的距离
window.innerHeight //屏幕的高度
图片懒加载的实现
<img data-src="./151654845377_.pic.jpg" height="800px" > <br>
<img data-src="./161654845508_.pic_hd.jpg" height="800px" > <br>
<img data-src="./1.jpeg" height="800px"> <br>
<img data-src="./2.jpeg" height="800px">
原生js实现
const isInView = (el) => {
const { top, left, height, width } = el.getBoundingClientRect();
const clientHeight =
window.innerHeight || document.documentElement.clientHeight;
const clientWidth = window.innerWidth;
document.documentElement.clientWidth;
if (top < clientHeight && left < clientWidth) {
return true;
}
return false;
};
const lazyload = () => {
const imgList = [...document.getElementsByTagName('img')];
if (!imgList.length) {
document.removeEventListener("scroll", lazyload);
return;
}
imgList.forEach((img) => {
if (!img.src && isInView(img)) {
img.src = img.dataset.src;;
}
});
};
// 第一次加载 屏幕内的图片正常显示,屏幕外的使用loading图片代替
window.onload = lazyload;
// 监听事件
document.addEventListener("scroll", lazyload, {passive: true});
使用IntersectionObserver API
document.addEventListener('DOMContentLoaded', function() {
let imgList = [...document.getElementsByTagName('img')];
if("IntersectionObserver" in window) {
let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach((item) => {
if (item.isIntersecting) {
item.target.src = item.target.dataset.src;
lazyImageObserver.unobserve(item.target);
}
});
});
// 对所有需要懒加载的图片进行 “暗中观察”
imgList.forEach(function(lazyImage) {
lazyImageObserver.observe(lazyImage);
});
} else {
console.log('您的浏览器不支持 IntersectionObserver');
}
})
响应式图片
网页在不同尺寸的设备上,都有良好的显示效果,叫做"响应式设计"(responsive web design)。
响应式设计的网页图像,就是"响应式图像"(responsive image)。
像素密度选择:srcset
属性
<img />
标签引入 srcset
属性来实现响应式图片。
srcset
属性用来指定多张图像,适应不同像素密度的屏幕。它的值是一个逗号分隔的字符串,每个部分都是一张图像的 URL,后面接一个空格,然后是像素密度的描述符。
<img srcset="foo-320w.jpg,
foo-480w.jpg 1.5x,
foo-640w.jpg 2x"
src="foo-640w.jpg">
像素描述的格式:像素密度倍数 + 字母x。 1x:单倍像素密度,可以省略。
浏览器根据当前设备的像素密度,选择需要加载的图像。如果srcset
属性都不满足条件,那么就加载src
属性指定的默认图像。
图像大小的选择:srcset
属性 + sizes
属性
像素密度的适配,只适合显示区域一样大小的图像。如果希望不同尺寸的屏幕,显示不同大小的图像,srcset
属性就不够用了,必须搭配sizes
属性。
<img srcset="foo-160.jpg 160w,
foo-320.jpg 320w,
foo-640.jpg 640w,
foo-1280.jpg 1280w"
sizes="(max-width: 440px) 100vw,
(max-width: 900px) 33vw,
254px"
src="foo-1280.jpg">
srcset
属性列出所有可用的图像。
宽度描述符就是图像原始的宽度,加上字符w
。
上例的四种图片的原始宽度分别为160像素、320像素、640像素和1280像素。sizes
属性列出不同设备的图像显示宽度。
sizes
属性给出了三种屏幕条件,以及对应的图像显示宽度。宽度不超过440像素的设备,图像显示宽度为100%;宽度441像素到900像素的设备,图像显示宽度为33%;宽度900像素以上的设备,图像显示宽度为 254px。- 浏览器根据当前设备的宽度,从
sizes
属性获得图像的显示宽度,然后从srcset
属性找出最接近该宽度的图像,进行加载。
WebP图片格式优化
WebP 是由谷歌(Google)推出的一种旨在加快图片加载速度的图片格式,在相同质量的情况下,WebP 的体积要比 JPEG 格式小 25% ~ 34%。
<picture>
<source type="image/svg+xml" srcset="pyramid.svg">
<source type="image/webp" srcset="pyramid.webp">
<img src="pyramid.png" alt="regular pyramid built from four equilateral triangles">
</picture>
始终在图像和视频元素上包括width和设置height尺寸属性。以确保在浏览器开始获取图像之前在页面上分配了足够的空间。这将最大程度地减少回流和重新布局。