本文介绍两种JavaScript图片加载方案:一是带进度条的延迟加载,利用data-src属性逐步替换src并更新进度;二是基于滚动位置的瀑布流预加载,监听滚动事件在图片即将可见时批量插入新图片。包含HTML结构、CSS样式及JS核心逻辑代码。
图片加载方案概述
本文主要演示两种图片加载效果的实现方式。
第一种方案针对页面图片数量较多的场景,提供带有进度条的加载提示。为了验证加载逻辑的正确性,代码中设置了1秒钟的加载间隔时间。
第二种方案根据页面滚动条的位置进行图片预加载,旨在用户无感知的情况下实现瀑布流加载效果。
延迟加载实现
一、延迟加载方案
核心实现思路如下:
- 在HTML的img标签中,将真实的图片地址存储在data-src属性内,同时为所有图片设置一个旋转的loading图片作为背景图(background)。
- 在JavaScript中,依次遍历每一个img元素,将data-src中的地址赋值给src属性,并移除背景图。
- 每成功加载一张图片,进度条的百分比数值随之相应更新。
- 若图片加载失败,则显示相应的错误提示信息。
HTML结构较为简单,使用一个div.picList容器包裹所有img元素,并添加一个简单的进度条div#loadBar。
<body>
<div class="picList">
<img class="lazy" data-src="pic/compressed/picList1.jg">
<img class="lazy" data-src="pic/compressed/picList2.jpg">
<img class="lazy" data-src="pic/compressed/picList3.jpg">
<img class="lazy" data-src="pic/compressed/picList4.jpg">
<img class="lazy" data-src="pic/compressed/picList5.jpg">
<img class="lazy" data-src="pic/compressed/picList6.jpg">
<img class="lazy" data-src="pic/compressed/picList7.jpg">
<img class="lazy" data-src="pic/compressed/picList8.jpg">
<img class="lazy" data-src="pic/compressed/picList9.jpg">
<img class="lazy" data-src="pic/compressed/picList10.jpg">
</div>
<div id="loadBar">
<div id="loadBarMask"></div>
</div>
</body>
CSS样式部分(使用SCSS编写,编译时会自动添加浏览器兼容前缀)。
.picList{
img{
width: 100px;
height: 100px;
position: relative;
/*加载失败时显示灰底文字*/
&:after{
content: "( ⊙ o ⊙ )加载失败";
font-size: 6px;
font-family: FontAwesome;
color: rgb(100, 100, 100);
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
background-color: #ddd;
}
}
}
.lazy{
background: url(../pic/loading.gif) center no-repeat;
border: 1px solid black;
}
#loadBar{
width: 200px;
height: 15px;
background: linear-gradient(90deg,#187103,#81b50b,#187103);
border: 10px solid white;
position: absolute;
top: 150px;
left: 50%;
margin-left: -100px;
#loadBarMask{
width: 70%;//这个数值显示没有加载成功的图片
height: 100%;
background-color: beige;
position: absolute;
right: 0;
}
}
CSS实现中有两个关键点需要注意:
- 首先,图片加载失败时显示的灰底文字位于img的after伪元素中。当图片加载失败且移除背景gif图片后,该部分内容及样式便会显示出来。
- 其次,进度条的样式设计较为简洁,由一层带有渐变的绿色层和一层白色层叠加而成。绿色代表已加载部分,白色代表未加载部分。显示时,直接控制白色层的宽度即可实现进度效果。
JavaScript部分代码(直接调用loadPicPerSecond()函数即可执行)。
var lazyPic = $('img.lazy');
var loadBarMask = $('#loadBarMask');
var picList = $('.picList');
var activePic = 0;
var totalPic = lazyPic.length;
/*每秒加载一张图片*/
function loadPicPerSecond(){
lazyPic.each(function(index){
var self = $(this);
//console.log(self[0].complete);
/*img标签已经事先写在html中,所以此时的complete状态全部都是true*/
setTimeout(function(){
src[index] = self.attr('data-src');
self.attr('src',src[index]);
self.removeClass('lazy');
//图片获得正确src地址之后,可以执行下面的onload操作
self[0].onload = function(){
//加载读条loadBar动画
countPic();
}
//图片获得的src地址不正确时,执行下面的onerror操作
self[0].onerror = function(){
/*this.style.background = 'url(pic/compressed/picList18.jpg) center no-repeat';*/
countPic();
}
},1000*index);
})
}
/*根据onload的执行情况来计算当前的图片加载进度.每onload一次,activePic就增加1*/
function countPic(){
activePic++;
var leftPic = totalPic - activePic;
var percentPic = Math.ceil(leftPic/totalPic*100);//没有加载的图片百分比,和loadBarMask的宽度占比配合
console.log("已加载"+(100-percentPic)+"%");
loadBarMask.css("width",percentPic+"%");
if(percentPic==0){
$('#loadBar').hide();
}
}
瀑布流预加载实现
二、瀑布流加载方案
核心实现思路如下:
- 监听窗口的滚动事件,当已加载图片中的最后一张即将进入可视窗口时,开始加载后续的图片。
- 假设所有图片地址已存储在一个JSON数据中,每次读取10张图片地址,加载完成后插入到现有瀑布流列表的末尾。
- 重复上述过程,直到所有图片加载完毕。
HTML结构与前述部分相同,只需将src属性写为正常地址即可。CSS样式完全一致。
JavaScript部分代码实现。
var lazyPic = $('img.lazy');
var loadBarMask = $('#loadBarMask');
var picList = $('.picList');
var scrollTop,
clientHeight,
scrollHeight;
var threshold = 200; //最后一张图片距离窗口200px的时候开始加载图片
var src = [];
var activePic = 0;
var totalPic = lazyPic.length;
//待加载的图片数据
var dirtSrc = "pic/compressed/picList";
var picData = {imgSrc:[
dirtSrc + "20.jpg",
dirtSrc + "21.jpg",
dirtSrc + "22.jpg",
dirtSrc + "23.jpg",
dirtSrc + "24.jpg",
dirtSrc + "25.jpg",
dirtSrc + "26.jpg",
dirtSrc + "27.jpg",
dirtSrc + "28.jpg",
dirtSrc + "29.jpg",
dirtSrc + "30.jpg",
dirtSrc + "31.jpg",
dirtSrc + "32.jpg",
dirtSrc + "33.jpg",
dirtSrc + "34.jpg",
dirtSrc + "35.jpg",
dirtSrc + "36.jpg",
dirtSrc + "37.jpg",
dirtSrc + "38.jpg",
dirtSrc + "39.jpg",
dirtSrc + "40.jpg",
dirtSrc + "41.jpg",
dirtSrc + "42.jpg",
dirtSrc + "43.jpg",
dirtSrc + "44.jpg",
dirtSrc + "45.jpg",
dirtSrc + "46.jpg",
dirtSrc + "47.jpg",
dirtSrc + "48.jpg",
dirtSrc + "49.jpg",
]};
//加载次数计数器
var scrollIndex = 0;
$(function(){
/*监听窗口滚动情况*/
$(window).on('scroll',function(){
scrollTop = $(window).scrollTop();//$(window).scrollTop()==document.body.scrollTop
clientHeight = $(window).height();
scrollHeight = picList.last().height();//picList.last()[0].clientHeight
/*目标与窗口的距离达到阈值时开始加载*/
if(scrollHeight-clientHeight-scrollTop < threshold){
scrollPic(10);
}
})
})
/*根据滚动程度加载图片,每次加载perAmount张*/
function scrollPic(perAmount = 10){
var totalAmount = perAmount * (scrollIndex+1);
//考虑到最后一次加载的时候,剩余的图片数量有可能达不到限定的每次加载的数量,这时候需要更改totalAmount的值
if(totalAmount>picData.imgSrc.length){
totalAmount = picData.imgSrc.length;
}
for(scrollIndex;scrollIndex<totalAmount;scrollIndex++){
var oimg = new Image();
oimg.src = picData.imgSrc[scrollIndex];
picList.append(oimg);
}
}
代码中涉及scrollTop、height等属性的取值对象,因容易混淆,故同时提供了原生JS和jQuery两种写法,便于后续直接调用。在明确数值关系后,只要满足特定条件即可触发加载逻辑。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。