最近在给公司写微商城,但是写完后单页的商品太多,导致图片加载很慢,而且我发现公司给服务器域名限制了单个IP器访问速度最高只有500K/s,面对这种情况,只好对图片进行懒加载处理了。
src-url
表示,然后将图片路径先赋值给src-url
(此时页面并不会真正显示图片)src-url
的图片路径赋值给img标签的src属性(这时图片会加载渲染)src-url
给删掉GIF效果图:
纵向的还是比较好实现的,直接监听window层的onscroll就好了,获取每一个图片距离窗口顶部的距离也会很容易,也不用考虑多个滚动条的情况。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>纵向懒加载图片title>
head>
<style>
body {
margin: 0;
}
.block .item {
width: 100vw;
height: 100vw;
}
.item img {
width: 100vw;
height: 100vw;
}
style>
<body>
<main>
<div class="block" id="blick-id">
div>
main>
body>
<script>
var imgArr = ['http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBA3X8RoF22*mTXfJ3*RNuBlDKADJ1uOLA7MGzFp8BJJXnqeNhEXGt9UcyseKRjTRL3g!!/b&bo=LAEsASwBLAEDCSw!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBAxNbk8AOn2*a26dMBu9JTc5ZMjUoOP8CXSWklFFu3wNX1doPdvuRbT1XP*LngYIcYQ!!/b&bo=qAKoAqgCqAIRCT4!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBAycZuvsrYM89XrUpvXk.BK7uk48c7uH5PB.O54*yiHLP2DcqIniegFyShf51OvTodw!!/b&bo=IAMgAyADIAMRCT4!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBA7XyxBYj1ChXgmpm2TPBJ9Qwg7Pg.b85HrbKUQMCkvQPZe8.CKMUzq4gadEk6ZLK7g!!/b&bo=LAEsASwBLAEDCSw!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBA2FzxFGTwkwju8grAh*GGjv1BSvZN3Ob9ZKplkXdZtK0dp7dwORVtLeFlZYYpPVWLA!!/b&bo=0ALQAtAC0AIRCT4!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBA3PQtUyBpTU*8PxS83qy6uNvksCAXfA*BjDhPE*k8S48m6I7.tvBznnNyMVpMUe2lA!!/b&bo=IAMgAyADIAMRCT4!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBA1E320PXRp5qlcLil8TkwsUJIBXnUyjiBKUyIvQnmY87Gx3eBsgtJlhJ5m4P8G12ww!!/b&bo=NgE2ATYBNgERCT4!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBA2mIh303WaCbhJsTAaw4ebe6WoKyO4SX*lp0lb3pwbXgfdMqCXj5VFP3D.dRrq9UZg!!/b&bo=9AH0AfQB9AERCT4!&rf=viewer_4',
]
//自定义字符串,拼接列表数据
var itemStr = '';
//自定义属性值src-url,用于暂存图片路径
imgArr.forEach((e) => {
itemStr += `
${e}" alt="">
`
})
//将拼接后的字符串渲染到列表中
document.getElementById('blick-id').innerHTML = itemStr;
window.onload = () => {
// 获取图片列表
var imgList = document.getElementsByClassName('block')[0].children;
// console.log(imgList);
// 初次渲染图片
lazyLoad(imgList)
// 二次监听滚动渲染图片
window.onscroll = function () {
lazyLoad(imgList);
};
}
//封装懒加载图片方法
function lazyLoad(imgList) {
//获取屏幕高度
var viewHeight = window.innerHeight;
// console.log(viewHeight)
//获取纵向滚动的值
var scrollHeight = document.documentElement.scrollTop || document.body.scrollTop;
// console.log(scrollHeight)
for (var i = 0; i < imgList.length; i++) {
// console.log(imgList[i].offsetTop)
//判断,当图片出现在页面时,
//imgList[i].offsetTop表示图片外层div距离设备窗口顶部的距离
if ((viewHeight + scrollHeight) >= imgList[i].offsetTop) {
//设置立即调用函数
(function (i) {
// 设置延时模拟图片加载缓慢的情况,实际项目中去求就好
setTimeout(function () {
// console.log(imgList[0].children[0]);
// console.log(imgList[i].children[0].getAttribute('src'));
//当前图片的节点
var imgNode = imgList[i].children[0];
//判断,如果图片的路径是空的,就对其进行赋值,且删除多余的自定义属性
if (imgNode.getAttribute('src') == null) {
imgNode.setAttribute('src', imgNode.getAttribute('src-url'));
imgNode.removeAttribute('src-url');
}
}, 1000)
})(i)
}
}
}
script>
html>
GIF效果图:
横向的考虑因数会比较多,因为一般横向展示物品不单只是一横排的,所以面对多人运动,呸,多排展示时,我们要分别对每一横排的滚动进行处理。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>横向懒加载图片</title>
</head>
<style>
body {
margin: 0;
}
.module .title {
text-align: center;
background-color: orange;
color: white;
}
.block {
display: flex;
overflow-x: auto;
overflow-y: hidden;
}
.block .item {
display: flex;
width: 50vw;
height: 50vw;
}
.item img {
width: 50vw;
height: 50vw;
}
</style>
<body>
<main>
<div class="module" id="module-id">
<!-- <div class="row">
<div class="title"></div>
<div class="block">
<div class="item">
<img src="" alt="">
</div>
</div>
</div> -->
</div>
</main>
</body>
<!-- <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script> -->
<script>
var imgObj = [
{
title: '板块一',
imgArr: ['http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBA3X8RoF22*mTXfJ3*RNuBlDKADJ1uOLA7MGzFp8BJJXnqeNhEXGt9UcyseKRjTRL3g!!/b&bo=LAEsASwBLAEDCSw!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBAxNbk8AOn2*a26dMBu9JTc5ZMjUoOP8CXSWklFFu3wNX1doPdvuRbT1XP*LngYIcYQ!!/b&bo=qAKoAqgCqAIRCT4!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBAycZuvsrYM89XrUpvXk.BK7uk48c7uH5PB.O54*yiHLP2DcqIniegFyShf51OvTodw!!/b&bo=IAMgAyADIAMRCT4!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBA7XyxBYj1ChXgmpm2TPBJ9Qwg7Pg.b85HrbKUQMCkvQPZe8.CKMUzq4gadEk6ZLK7g!!/b&bo=LAEsASwBLAEDCSw!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBA2FzxFGTwkwju8grAh*GGjv1BSvZN3Ob9ZKplkXdZtK0dp7dwORVtLeFlZYYpPVWLA!!/b&bo=0ALQAtAC0AIRCT4!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBA3PQtUyBpTU*8PxS83qy6uNvksCAXfA*BjDhPE*k8S48m6I7.tvBznnNyMVpMUe2lA!!/b&bo=IAMgAyADIAMRCT4!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBA1E320PXRp5qlcLil8TkwsUJIBXnUyjiBKUyIvQnmY87Gx3eBsgtJlhJ5m4P8G12ww!!/b&bo=NgE2ATYBNgERCT4!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBA2mIh303WaCbhJsTAaw4ebe6WoKyO4SX*lp0lb3pwbXgfdMqCXj5VFP3D.dRrq9UZg!!/b&bo=9AH0AfQB9AERCT4!&rf=viewer_4',
]
},
{
title: '板块二',
imgArr: ['http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBA2mIh303WaCbhJsTAaw4ebe6WoKyO4SX*lp0lb3pwbXgfdMqCXj5VFP3D.dRrq9UZg!!/b&bo=9AH0AfQB9AERCT4!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBA1E320PXRp5qlcLil8TkwsUJIBXnUyjiBKUyIvQnmY87Gx3eBsgtJlhJ5m4P8G12ww!!/b&bo=NgE2ATYBNgERCT4!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBA3PQtUyBpTU*8PxS83qy6uNvksCAXfA*BjDhPE*k8S48m6I7.tvBznnNyMVpMUe2lA!!/b&bo=IAMgAyADIAMRCT4!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBA2FzxFGTwkwju8grAh*GGjv1BSvZN3Ob9ZKplkXdZtK0dp7dwORVtLeFlZYYpPVWLA!!/b&bo=0ALQAtAC0AIRCT4!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBA7XyxBYj1ChXgmpm2TPBJ9Qwg7Pg.b85HrbKUQMCkvQPZe8.CKMUzq4gadEk6ZLK7g!!/b&bo=LAEsASwBLAEDCSw!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBAycZuvsrYM89XrUpvXk.BK7uk48c7uH5PB.O54*yiHLP2DcqIniegFyShf51OvTodw!!/b&bo=IAMgAyADIAMRCT4!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBAxNbk8AOn2*a26dMBu9JTc5ZMjUoOP8CXSWklFFu3wNX1doPdvuRbT1XP*LngYIcYQ!!/b&bo=qAKoAqgCqAIRCT4!&rf=viewer_4',
'http://photogz.photo.store.qq.com/psc?/V14ZaBeY27gVgy/BbSbWrmEw8nJ9LYcvxlBA3X8RoF22*mTXfJ3*RNuBlDKADJ1uOLA7MGzFp8BJJXnqeNhEXGt9UcyseKRjTRL3g!!/b&bo=LAEsASwBLAEDCSw!&rf=viewer_4',
]
},
]
//自定义字符串,拼接列表数据
var moduleStr = '';
//自定义属性值src-url,用于暂存图片路径
imgObj.forEach((element, index) => {
moduleStr +=
`<div class="row">
<div class="title">${element.title}</div>
<div class="block" id="block${index}">
${element.imgArr.map((e) => {
return `<div class="item">
<img src-url="${e}" alt="">
</div>`}).join('')}
</div>
</div>`
})
//将拼接后的字符串渲染到列表中
document.getElementById('module-id').innerHTML = moduleStr;
window.onload = () => {
//全部板块的节点
var rowLists = document.getElementsByClassName(`module`)[0].children;
// console.log(rowLists)
lazyLoad(rowLists);
}
//封装懒加载图片方法
function lazyLoad(rowLists) {
//获取可视高度(屏幕高度)
var viewWidth = window.innerWidth;
/*注意,如果这里用var定义i,需要再包裹一层立即调用函数*/
for (let i = 0; i < imgObj.length; i++) {
//设置立即调用函数
// (function (i) {
// console.log(imgList)
//封装加载每一个商品的方法
function lazyLoadItem(e) {
//滚动条距离窗口左侧的距离
var scrollLeft = null;
//判断,如果e等于空,说明是第一次渲染页面
if (e == '') {
scrollLeft = 0;
} else {
scrollLeft = e.target.scrollLeft;
}
for (let n = 0; n < imgObj[i].imgArr.length; n++) {
// console.log(viewWidth + scrollLeft)
// console.log(viewWidth / 2 * n)
//每一个商品图片外层div距离设备窗口左边的距离
var offsetLeft = rowLists[i].children[1].children[n].offsetLeft;
// console.log(offsetLeft)
if (viewWidth + scrollLeft > offsetLeft) {
//设置立即调用函数
(function (n) {
// 设置延时模拟图片加载缓慢的情况,实际项目中去求就好
setTimeout(function () {
// 当前商品图片的路径
var itemImg = rowLists[i].children[1].children[n].children[0];
// console.log(itemImg)
//判断,如果图片的路径是空的,就对其进行赋值,且删除多余的自定义属性
if (itemImg.src == '') {
//获取真的图片路径
var goodsSrc = itemImg.getAttribute('src-url');
// 替换设置图片
itemImg.setAttribute('src', goodsSrc);
//清理掉原来的属性
itemImg.removeAttribute('src-url');
}
}, 1000)
})(n)
}
}
}
// 初次渲染图片
lazyLoadItem('');
//监听不同滑块的滚动
document.getElementById(`block${i}`).addEventListener("scroll", function (e) {
// console.log(e)
// 二次渲染图片
lazyLoadItem(e);
})
// })(i)
}
}
</script>
</html>
细心的同学应该会发现一个问题,那就是每次监听到滚动变化时都会执行lazyLoad懒加载方法,然而你滑动一次屏幕可能触发了几十次这个方法,所以非常消耗性能,可能会出现滑动时有卡顿的现象。我在网上找了一些滚动停止触发的事例都不怎么理想(貌似都是用setTimeout执行方法,每次监听时都清理clearTimeout计时器,然后用scrollTop来判断执行前后是否相等,相等说明停止了),最后我在菜鸟教程jQuery Mobile 滚屏事件中找到了不错的解决方案,可以参考一下面的例子
我们只需要引入jquery全家桶,然后更改上面例子的这部分代码就可以了
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>jquery.mobile优化版纵向懒加载图片title>
<link rel="stylesheet" href="https://apps.bdimg.com/libs/jquerymobile/1.4.5/jquery.mobile-1.4.5.min.css">
<script src="https://apps.bdimg.com/libs/jquery/1.10.2/jquery.min.js">script>
<script src="https://apps.bdimg.com/libs/jquerymobile/1.4.5/jquery.mobile-1.4.5.min.js">script>
head>
<script>
window.onload = () => {
var imgList = document.getElementsByClassName('block')[0].children;
lazyLoad(imgList)
//在这里用jquery.mobile的scrollstop处理监听结束
$(document).on("scrollstop", function () {
// alert("停止滚动!");
console.log("停止滚动!")
lazyLoad(imgList);
});
}
script>
我们只需要引入jquery全家桶,然后修改一下上面例子的监听方式和获取到scrollLeft的方式就好了
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>jquery.mobile优化版横向懒加载图片title>
<link rel="stylesheet" href="https://apps.bdimg.com/libs/jquerymobile/1.4.5/jquery.mobile-1.4.5.min.css">
<script src="https://apps.bdimg.com/libs/jquery/1.10.2/jquery.min.js">script>
<script src="https://apps.bdimg.com/libs/jquerymobile/1.4.5/jquery.mobile-1.4.5.min.js">script>
head>
<script>
function lazyLoad(rowLists) {
var viewWidth = window.innerWidth;
for (let i = 0; i < imgObj.length; i++) {
function lazyLoadItem(e) {
//这里可以用jquery直接获取到scrollLeft
var scrollLeft = $(`#block${i}`).scrollLeft();
for (let n = 0; n < imgObj[i].imgArr.length; n++) {
var offsetLeft = rowLists[i].children[1].children[n].offsetLeft;
if (viewWidth + scrollLeft > offsetLeft) {
(function (n) {
setTimeout(function () {
var itemImg = rowLists[i].children[1].children[n].children[0];
if (itemImg.src == '') {
var goodsSrc = itemImg.getAttribute('src-url');
itemImg.setAttribute('src', goodsSrc);
itemImg.removeAttribute('src-url');
}
}, 1000)
})(n)
}
}
}
lazyLoadItem('');
//在这里用jquery.mobile的scrollstop处理监听结束
$(`#block${i}`).on("scrollstop", function () {
// alert("停止滚动!");
console.log("停止滚动!")
lazyLoadItem();
});
}
}
script>
当然,如果你觉得引入jquery全家桶太费空间了 。那么可以做一个函数防抖,效果也是不错的。
// 函数防抖
var timer = false;
window.onscroll = function () {
clearTimeout(timer);
timer = setTimeout(function () {
console.log("函数防抖");
lazyLoad(imgList);
}, 100);
};
最后呢,其实在for循环输出列表时可以先赋值一张伪图(也就是加载图片中gif类型的轻量级图片)给img标签的src,然后在setAttribute图片替换这一步中用onload监听真的图片加载完了再把url赋值给src,这样就不会产生图片一段一段加载的感觉,这个看个人的项目需求吧。加油同志们!
白嫖罚多人运动,请自重 (╯°Д°)╯︵┻━┻
♩
♪
♫
♬
♩♩
♪
♩
♫
♬
♪♪
♫
♩
♪
♬
♫♫
♬
♩
♪
♫
♬♬
不要误会