专栏首页前端说吧js - 预加载+监听图片资源加载制作进度条

js - 预加载+监听图片资源加载制作进度条

这两天遇到一个新需求:一个一镜到底的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值赋给进度条的宽度即可。 至于进度条怎么做,看我这篇博文。css案例 - 评分效果的星星✨外衣

五、数字动画效果: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');
    });
  });
});

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • canvas - drawImage()方法绘制图片不显示的问题

    事情是这样的,在我看完w3c的介绍和很有说服力和教学力的demo后,本着实践出真知的思想决定上手一试,这一试不要紧~

    xing.org1^
  • 【Python系统学习01】print函数的用法

    print - Python中打印信息的函数,可以打印代码运行结果,帮助我们了解代码执行状态。

    xing.org1^
  • Vue + TypeScript 踩坑总结

    vue 和 TypeScript 结合的情况下,很多写法和我们平时的写法都不太一样,这里总结我项目开发过程中遇到的问题和问题的解决方案 有些问题可能还没解决,...

    xing.org1^
  • 《前端那些事》聊聊前端的按需加载

    前沿:按需加载是性能优化其中的一个环节,可以是图片的按需加载,也就是lazyload来实现按需加载的场景,也可以是组件库的引入,只需部分组件的使用而无需全局引入...

    树酱
  • 双亲委派机制

    爱学习的孙小白
  • 我竟然不再抗拒 Java 的类加载机制了

    很长一段时间里,我对 Java 的类加载机制都非常的抗拒,因为我觉得太难理解了。但为了成为一名优秀的 Java 工程师,我决定硬着头皮研究一下。

    沉默王二
  • 虚拟机类加载机制

    虚拟机把字节码文件从磁盘加载进内存的这个过程,我们可以粗糙的称之为「类加载」,因为「类加载」不仅仅是读取一段字节码文件那么简单,虚拟机还要进行必要的「验证」、「...

    Single
  • 人机交互,6种最被BAT认可的加载模式

    作为用户体验设计师,不管是产品、交互还是UI,都习惯于站在人机交互的角度去思考产品设计问题,在这个过程中我们往往会忽略了一个重要的过程:数据传输。先看下面这张图...

    BestSDK
  • JVM - 双亲委派机制

    父加载器不是“类加载器的父类加载器”!!! 双亲委派是一个孩子向父亲(上级)方向,然后父亲向孩子方向的双亲委派过程

    Parker
  • 商城项目-优化

    cwl_java

扫码关注云+社区

领取腾讯云代金券