js图片加载效果(延迟加载+瀑布流加载)
概述
详细
主要做了两种图片加载的效果
一种是遇到页面图片比较多的时候,带读条效果的加载提示(为了验证正确加载,设置了1秒钟的加载间隔时间)
另外一种是根据滑块的位置进行图片的预加载,在用户不察觉的情况下,实现瀑布流的加载效果
一、延迟加载
1、需要准备什么环境
2、需要开通什么服务,如果有的话
3、本例子实现什么功能
二、程序实现
主要思路:
-
HTML的img标签中,将正确的地址存在data-src属性中,给所有图片设置一个转圈圈的loading图片作为background
-
js中,依次读取每一个img,将data-src中的地址替换到src中,去掉background
-
每成功加载一张图片,进度条的百分比进行相应的变化。
-
如果加载不成功,就提示图片加载错误。
HTML结构很简单,就是一个div.picList包裹了所有img,然后加上一个简单的进度条div#loadBar
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | < 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,编译时会自动加上各种兼容前缀)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | .lazy{ background : url (../pic/loading.gif) center no-repeat ; border : 1px solid black ; } #loadBar{ width : 200px ; height : 15px ; background : linear-gradient( 90 deg, #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伪类中,当图片加载失败,又去掉了background的gif图片之后,就会显示这个部分的内容及样式。
-
一个是进度条的样式。写得很简单,主要是一层带渐变的绿色和一层白色叠在一起。绿色表示已加载,白色表示未加载。显示的时候,直接控制白色那层的宽度即可。
js部分(直接执行loadPicPerSecond()即可)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | 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完全一样。
js部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | 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都写上了,以后可以直接用。将数值关系搞定之后,只要满足条件就触发加载即可。
三、运行效果与文件截图
1、运行效果
2、文件截图
双击"图片加载.html"即可运行。
四、后记·兼容性问题
拿到IE8之下运行时,发现img.onload后面的function打死都不执行,IE8智障到不能完成 img.onload = function(){}这么初级的代码么?
去查了资料之后,发现IE8虽然白痴,但还算没有智障到无药可救。
onload是可以调用的,但是要放在src的赋值之前。
简单来说,就是要先告诉浏览器图片加载完要怎么处理,再让它去加载图片。避免因为加载缓冲区的速度太快,在没有告诉它加载完要怎么办时,它已经加载完了。而其它浏览器则是从缓冲区读取到图片时就执行onload。
注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?