zoukankan      html  css  js  c++  java
  • 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');
        });
      });
    });
    

      

    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

  • 相关阅读:
    Android ANR的产生与分析
    The module is an Android project without build variants, and cannot be built
    ExpandableListView使用(三)-ScrollView嵌套ExpandableListView,列表显示不全
    在代码中设置RelativeLayout布局中标签的android:layout_toLeftOf、android:layout_toRightOf等属性
    git报ssh variant 'simple' does not support setting port解决办法
    解决ScrollView嵌套RecyclerView出现item显示不全的问题
    解决ScrollView嵌套RecyclerView的显示及滑动问题
    Android在开发中的使用技巧之解决ScrollView嵌套RecyclerView出现的系列问题
    android listview优化:滑动时颜色错乱问题
    映射的介绍与使用
  • 原文地址:https://www.cnblogs.com/padding1015/p/9639966.html
Copyright © 2011-2022 走看看