图片懒加载是前端开发过程中非常常见的一个功能。图片懒加载本质上是通过检测可见区域来判断是否发送网络请求,从而优化网页加载速度,本文将实现图片懒加载功能。
1. 效果预览
2. 实现思路
对于图片懒加载,实际的实现思路实际上就是当图片处于或即将处于可视窗口中时,网页发送网络请求,从而加载图片。
之所以不一开始就加载图片,是因为大量图片同一时间加载,会造成浏览器页面的卡顿,所以才有了懒加载的需求。
所以懒加载的核心就是
const windowHeight = window.innerHeight;
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
const offsetTop = imgContainer.offsetTop;
(windowHeight + scrollTop) > offsetTop;
即窗口高度+
滚动高度>
图片距离顶部的高度
但实际使用过程中,为了让用户有更好的体验,上面的逻辑通常是下面这个样子
(windowHeight + scrollTop +256) > offsetTop;
这里可以是256,也可以是更大或更小的数值,同样也是实现懒加载,但是由于多加了一点距离,这样就保证了大多数时候,用户总能及时看到图片,而不是看到占位的背景切换成图片。
3. 实现代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.container {
width: max-content;
height: 400px;
}
/*=========要加载的图片添加lazy class===========*/
/*根据自己需要,修改图片加载前的颜色,或者用展位图代替*/
.lazy {
width: 100%;
height: 100%;
scale: 1;
background-color: antiquewhite;
overflow: hidden;
}
/*设置lazy内部图片的style,根据自己需要调整,这里是填充显示中间部分*/
/*悬浮时将会缩放图片*/
.lazy > img {
width: 100%;
height: 100%;
object-fit: cover;
/*property duration timing-function delay*/
transition: all 0.2s ease-in 0s;
}
.lazy > img:hover {
transform: scale(1.2, 1.2);
}
/*=============================*/
</style>
</head>
<body>
<h1>H1</h1>
<div>H1</div>
<div>H1</div>
<div class="container">
<div class="lazy" data-src="https://www.flywinter.com/assets/images/cover/2022-05-10-Veiled.png"></div>
</div>
<div class="container">
<div class="lazy" data-src="https://www.flywinter.com/assets/images/cover/2022-05-10-Veiled.png"></div>
</div>
<div class="container">
<div class="lazy" data-src="https://www.flywinter.com/assets/images/cover/2022-05-10-Veiled.png"></div>
</div>
<div class="container">
<div class="lazy"
data-src="https://www.flywinter.com/assets/images/cover/2022-05-10-%E9%9B%AA%E8%A7%A3%E3%81%91.png"></div>
</div>
<div class="container">
<div class="lazy"
data-src="https://www.flywinter.com/assets/images/cover/2022-05-10-%E9%9B%AA%E8%A7%A3%E3%81%91.png"></div>
</div>
<div class="container">
<div class="lazy"
data-src="https://www.flywinter.com/assets/images/cover/2022-05-10-%E9%9B%AA%E8%A7%A3%E3%81%91.png"></div>
</div>
<div class="container">
<div class="lazy" data-src="https://www.flywinter.com/assets/images/cover/2022-05-09-mikasa-sakura.png"></div>
</div>
<div class="container">
<div class="lazy" data-src="https://www.flywinter.com/assets/images/cover/2022-05-09-mikasa-sakura.png"></div>
</div>
<div class="container">
<div class="lazy" data-src="https://www.flywinter.com/assets/images/cover/2022-05-09-mikasa-sakura.png"></div>
</div>
<h2>H2</h2>
</body>
<script type="text/javascript">
/**
* 另一种实现思路,使用时,先新建被div包裹的img标签,
* 这样就不需要重新创建元素,直接给lazy里面的img标签赋值即可
* 但是缺点就是一定几率用户会看到加载失败的图片样式,影响体验
* 可以通过背景图片,增大判断距离来解决
*
* 下面的实现思路是为每个添加了lazy的元素添加标签,
* 只要处于可视范围,就新建img元素,并且为lazy元素设置属性,
* 只要设置了属性为true,代表已经创建了元素,即已经加载,
* 就不需要重新加载了
*/
const lazyLoad = (imgContainers) => {
//窗口高度
const windowHeight = window.innerHeight;
//滚动条滚动距离
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
for (let i = 0; i < imgContainers.length; i++) {
const imgContainer = imgContainers[i];
const offsetTop = imgContainer.offsetTop;
const loaded = imgContainer.getAttribute('data-loaded');
//滚动+窗口的高度>图片元素到顶部的距离
//多加256的高度,让图片接近的时候就开始加载
//这时图片在窗口
// <----windowHeight + scrollTop---->
// <-----------offsetTop------------>imageContainer
//如果图片显示了,并且没有加载过,就加载图片,防止重复创建img
const isShow = (windowHeight + scrollTop +256) > offsetTop;
if (isShow && loaded === 'false') {
const img = document.createElement('img');
const imgSrc = imgContainer.getAttribute('data-src');
img.src = imgSrc;
img.alt = imgSrc.split("/").pop()
imgContainer.appendChild(img)
imgContainer.setAttribute('data-loaded', 'true')
}
}
};
//HTML元素都加载完毕了再添加事件
window.addEventListener('load', () => {
const imgContainers = document.querySelectorAll('.lazy');
for (let i = 0; i < imgContainers.length; i++) {
imgContainers[i].setAttribute('data-loaded', 'false')
}
//有时即使元素都加载完毕了,网页还是空白,所以延迟
//但是这里延迟可以去掉,只保留lazyLoad(),
// 因为实际的要求往往是只要请求网页就马上加载可视的图片,加了延迟反而显得有些卡
setTimeout(() => {
lazyLoad(imgContainers)
}, 50)
//只要滚动,就检测是不是需要请求图片
window.addEventListener('scroll', () => {
lazyLoad(imgContainers);
}
)
})
</script>
</html>
4. 使用方法
将js代码以及.lazy
和.lazy > img
这两个class拷贝到项目中,原来需要用到img标签的地方,替换为<div class="lazy" data-src="imagePath">
,这样就可以实现图片懒加载
赏
Alipay
