博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
js - 预加载+监听图片资源加载制作进度条
阅读量:6577 次
发布时间:2019-06-24

本文共 4468 字,大约阅读时间需要 14 分钟。

这两天遇到一个新需求:一个一镜到底的h5动画。因为功能的特殊性,就要求我们提前监听页面的静态图片是否全部加载完毕。即处理预加载。

总结下来,下次这种需求需要提前注意以下几点:

 

一、图片而不是背景图

本来,我所用到的图都是用背景图制作的(因为非接口返回的图片都要求用背景图)。

但是监听静态图片时,后来发现所用的方法监听不到背景图,所以改成了图片。

这是一个坑。

 

二、获取新加载的图片:Img.load()

1、要监听图片我们要先获取到页面中的所有图片:

jq的方法:find()

var MyImg = $(body).find('img');

 

很简单的解决了这个问题。

MyImg得到的是目标元素中的所有图片的集合。

2、然后我们要遍历所有的图片,好判断是否加载完毕:

依然是jq的方法:each()

MyImg.each(function(){    //在这里实现 分别对每一个图片的图片加载结果 的监听。})

3、然后说如何监听图片加载:

万年青jq方法:load()

Img.load(function(){    // 回调里,执行加载完毕一个的记录处理})

还好这次用的jq写的代码,省了不少事。

为了记录图片加载完毕的个数,我在全局设置一个变量:

var sum = 0;

并准备一个方法让sum累加

function sumAdd(){    sum++;}

然后load方法的回调里,调用sumAdd

MyImg.load(()=>{      // 用于新加载的图片      sumAdd(1);});

 

最后页面加载完成后成功得到 sum=7;(本次案例页面7张图)

 

三、获取缓存的图片:Img.complete

now

图片加载是能控制了,但是为什么我一刷新他又监听不到了?

哦!原来页面加载完毕后刷新,再展示的图片都是缓存的图,而load又监听不到缓存的图。

要了我的老命了。

于是我又找,什么方法能监听缓存的图啊?
目标锁定了js里的img.complete。注意划重点是js的属性
所以这里使用上要注意,因为我获取的dom对象是jq的,要转成js的再调complete属性,于是代码直接是:

if(MyImg[0].complete){    // 用于缓存图片    sumAdd();}

 

有了之前准备的sumAdd函数做接应,缓存图片的个数也能计算出来了。

至此,一个非常简易又简陋的监听就完成了。

 

题外话

之前不是这么做的,而是load方法里累加load的个数,complete里累加缓存的个数。

在电脑上测试,两者河井互不犯,相安无事。

但是到手机上发现,会有6张缓存图1张加载图,导致下边要说的加载进度计算错误,先是变成70%,又变回20%。

后来才改成这两种情况都累加到一处了。

 

四、预加载进度计算并展示

好了,现在需求升级。

为了友好的用户体验,你在后台加载图片的时候,用户不能只看到一个加载中,等半天不知道到底有没有反应。

所以我们要给用户一个及时的反馈,就要获取图片加载的进度。

思路就是 :

加载进度 = 已加载图片资源个数/总的图片资源个数*100+'%';

 

有了公式,又有之前我们准备的sum(当前加载个数),这个加载进度轻而易举就能得到了:

let progress = Math.ceil(sum/7*100);

 

7是当前页面中图片的总个数。而Math.ceil向上取整是为了在除不尽的时候不会出现小数点或99.9999%的情况。
当然为了控制万一超过100的情况,只需要保险设置一下:

progress>=100?100:progress

 

如果加载进度想做成进度条效果,只需要把得到的progress值赋给进度条的宽度即可。

至于进度条怎么做,看我这篇博文。

 

五、数字动画效果:animate()

后来我又想,进度条旁边加数字展示岂不是更好?

而作为一个有些许追求的程序员,我又不想直接做成数字是多少就生硬切换成多少的效果。

我想做逐渐变化的数字动画效果

这就要另一个方法上场了。

对,没错,还是jq的方法 - animate()方法:

利用其step属性达到动画逐帧改变的效果,也就是文字从1累加渐变成100,而不是生硬的跳转为100。

这个方法的用法是这样的:

$('#loadingTxts').animate({count: progress},{    duration: 350,    step: function() {        if(isNaN(this.count)){            this.count = 0;            return;        }        let boxText = Math.ceil(Number(this.count));        if(boxText >= 100){            boxText = 100;            //接下来执行预加载完毕,页面开始展示            ...        }        $('#loadingTxts').text(boxText+'%');// 文字展示        $('.progress').css('width',boxText+'%'); // 进度条宽度设置    }});

 

 

 

一个坑接一个坑,最后我们被折磨得没了生气的力气。

大致参考代码:

$(function () {  let nameLink = 'https://www.test.com/test/dist/images/',    nameArr = ['1', '2', '3', '4', '5', '6', '7'],    myImgs = $('.baby-box').find('img'),    downAndCache = 0;  function progressAni(i){    downAndCache += i;    let progreVal = Math.ceil(downAndCache/nameArr.length*100);    // 文字-单值变化动画    $('#txtsBox').animate({      count: progreVal    },{      duration: 350,      step: function() {        if(isNaN(this.count)){          this.count = 0;          return;        }        let numberTxt = Math.ceil(Number(this.count));        if(numberTxt >= 100){          numberTxt = 100;          $('.loading').fadeOut();        }        $('#txtsBox').text(numberTxt+'%');        $('#progressBox').css('width',numberTxt+'%');      }    });  }  myImgs.each(function(a){    let Img = $(this);    if(Img[0].complete){      // 用于缓存图片      progressAni(1);    }    Img.load(()=>{      // 用于新加载的图片      progressAni(1);    });    Img.error(function() {      // 图片加载失败,可以选择替换图片      console.log(Img.attr('src'));      Img.attr('src',nameLink + nameArr[a] + '.jpg');    });  });});

  

 

 

2018-09-13 17:32:28

相同思路的 一段其他的处理方法: 2018-10-26  14:00:21

1 //加载图片 2 var loadImgIndex = 0, 3     path = 'images/'; 4 exports.loadImg = function(arr,callback){ 5     var len = arr.length, 6         callback = callback || function(){}; 7     if(!len){ 8         return; 9     }10     (function loading(){11         var img = new Image();12         img.onload = function(){13             if(loadImgIndex == len-1){14                 callback();15             }else{16                 loadImgIndex++;17                 console.log('图片已经加载:' + Math.floor(loadImgIndex/len*100) + '%');18                 loading();19             }20         }21         img.src = path + arr[loadImgIndex];22         img.onerror = function(){23             console.log('加载失败');24             setTimeout(callback,1000);25         }26     })();27 28 --------------------- 29 //作者:kongjunchao159 30 //来源:CSDN 31 //原文:https://blog.csdn.net/kongjunchao159/article/details/49587573 32 //版权声明:本文为博主原创文章,转载请附上博文链接!

还有这个文章,写的讲解也很好。通俗易懂:

 https://blog.csdn.net/ssisse/article/details/51655644?utm_source=blogxgwz0

转载于:https://www.cnblogs.com/padding1015/p/9639966.html

你可能感兴趣的文章
在Java中,以下关于方法重载和方法重写描述正确的是?
查看>>
Codeforces Round #315 (Div. 2A) 569A Music (模拟)
查看>>
提升代码内外部质量的22条经验(转载)
查看>>
利用Linq对集合元素合并、去重复处理
查看>>
AS3.0 Bitmap类实现图片3D旋转效果
查看>>
BZOJ1876:[SDOI2009]SuperGCD——C++高精度良心题解
查看>>
2018-2019 20165226 Exp5 MSF基础应用
查看>>
yum安装的JDK的没有配置环境变量但是在/usr/bin下面都做了软链接
查看>>
设备坐标和逻辑坐标
查看>>
Django 自带 user 字段扩展及头像上传
查看>>
Android Studio快捷键
查看>>
Maven学习篇一:依赖了解
查看>>
SOA:面向服务编程——竹子整理
查看>>
Django 框架之前
查看>>
【java】安全加密MessageDigest的功能及用法【hash一致性算法】
查看>>
ZOJ 2107 Quoit Design(分治法解最近对模板题)
查看>>
Android学习系列(9)--App列表之分组ListView
查看>>
基于数据库复制的技术架构讨论
查看>>
Android学习网站(1)
查看>>
jenkins Email-ext plugin插件中Pre-send Script设置说明
查看>>