图片预加载之无序加载

当一个页面的图片很多,或者有图片很大的时候,就可以使用图片预加载的技术来提升用户的体验效果。图片预加载技术核心是用到了Image对象,将图片预先存在Image对象中,当需要展示这张图片的时候,就可以直接从浏览器缓存中获取,这样就不会出现页面假死的情况。
今天,我打算用图片预加载技术来做一个简单的图片相册,最终的效果图如下:
这里写图片描述
它的html结构如下:

<div class="box">
  <img src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1532191258391&di=a10eff830ac73774f631af907baf3d51&imgtype=0&src=http%3A%2F%2Fimg4.duitang.com%2Fuploads%2Fitem%2F201511%2F19%2F20151119180529_ckQYx.jpeg" alt="pic" id="img" width="1200"/>
  <p>
    <a href="javascript:;" class="btn" data-control="prev">上一页</a>
    <a href="javascript:;" class="btn" data-control="next">下一页</a>
  </p>
</div>

<div class="loading">
  <p class="progress">0%</p>
</div>

其css代码如下:

html, body {
  height: 100%;
}
a {
  text-decoration: none;
}
.box {
  text-align: center;
}
.btn {
  display: inline-block;
  height: 30px;
  line-height: 30px;
  border: 1px solid #ccc;
  background-color: #fff;
  padding: 0 10px;
  margin-right: 50px;
  color: #333;
}
.btn:hover {
  background-color: #eee;
}
.loading {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%; /* 高度值继承自父类 所以需要在html或body中设置height值 */
  background-color: #eee;
  text-align: center;
  font-size: 30px;
}
.progress {
  margin-top: 300px;
}

其js代码如下:

var imgs = [
  'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1532191258391&di=a10eff830ac73774f631af907baf3d51&imgtype=0&src=http%3A%2F%2Fimg4.duitang.com%2Fuploads%2Fitem%2F201511%2F19%2F20151119180529_ckQYx.jpeg',
  'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1532192442862&di=39c538bcdd01603d44174ac7197df280&imgtype=jpg&src=http%3A%2F%2Fimg4.imgtn.bdimg.com%2Fit%2Fu%3D4144665989%2C3104020614%26fm%3D214%26gp%3D0.jpg',
  'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1532191258390&di=f68f55ddb98094899a724dc36cade062&imgtype=0&src=http%3A%2F%2F2t.5068.com%2Fuploads%2Fallimg%2F140820%2F39_140820105334_3.jpg',
  'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1532191258387&di=1e1d5c983e4204c6fe4e79424a896d41&imgtype=0&src=http%3A%2F%2Fi1.hdslb.com%2Fbfs%2Farchive%2Fe35d60332d01a70ca2cd1d83a4ac95188464f7db.jpg',
  'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1532191258387&di=41ca4b51770505410e4b776454f485d4&imgtype=0&src=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Farchive%2F70daa8d4db1d31016c4b09f813bca5e71cdf954b.jpg',
  'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1532192495872&di=264c5fc7394abb73dff253aee02f6272&imgtype=0&src=http%3A%2F%2Fimg5.duitang.com%2Fuploads%2Fitem%2F201410%2F01%2F20141001213754_etBCG.jpeg',
  'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1532192657412&di=1b3b6daddda31c05f9bd52cf9f9d16cf&imgtype=jpg&src=http%3A%2F%2Fimg3.imgtn.bdimg.com%2Fit%2Fu%3D2612913783%2C2206253269%26fm%3D214%26gp%3D0.jpg'
];

var index = 0;
    len = imgs.length,
    count = 0,
    $progress = $('.progress');

// 图片预加载
$.each(imgs, function (i, src) {
  var imgObj = new Image();

  // $(imgObj)可以使imgObj变成jQuery对象
  // error是增加程序的健壮性,即使有某张图片无法正常加载也不影响后续图片的加载
  $(imgObj).on('load error', function () {
    $progress.html(Math.round((count + 1) / len * 100) + '%');

    if (count >= len - 1) {
      $('.loading').hide();
      document.title = '1/' + len;
    }
    count++;
  });

  imgObj.src = src;
});

$('.btn').on('click', function () {
  if ('prev' === $(this).data('control')) { // 上一张
    index = Math.max(0, --index);
  } else {
    index = Math.min(len - 1, ++index);
  }
  document.title = (index + 1) + '/' + len;
  $('#img').attr('src', imgs[index]);
})

其中的主要逻辑是先用一个数组将图片资源存储起来,然后将图片资源存在Image对象中,当需要展示图片的时候,由于图片已经预先存储在Image对象中了,所以浏览器可以直接从缓存中获取图片资源。
然后,我们也可以将图片预加载的逻辑提取出来,封装成一个jQuery插件,代码如下:

// 图片预加载
// 用闭包来模拟局部作用域(块级作用域)
// 传递jQuery对象到闭包内并用$来接收
(function($) {

  function PreLoad(imgs, options) {
    this.imgs = (typeof imgs === 'string') ? [imgs] : imgs;
    /**
     * 将传递进来的变量与默认的变量相容合
     * 如果传递了变量进来就用传递进来的变量
     * 如果没有传递变量进来就用默认值
     */
    this.opts = $.extend({}, PreLoad.DEFAULTS, options); // 用options覆盖PreLoad.DEFAULTS形成新对象赋给opts

    // 方法名前加_表明此方法只在内部使用,不提供外部调用
    this._unoredered();
  }
  // 设置默认参数
  PreLoad.DEFAULTS = {
    each: null, // 每一张图片加载完毕后执行
    all: null   // 所有图片加载完毕后执行
  };
  // 将方法写在原型上 每次实例化此对象的时候就只有一份这样的方法
  PreLoad.prototype._unoredered = function () { // 无序加载
    var imgs = this.imgs,
        opts = this.opts,
        count = 0,
        len = imgs.length;
   $.each(imgs, function (i, src) {
     if (typeof src != 'string') return;

     var imgObj = new Image();

     // $(imgObj)可以使imgObj变成jQuery对象
     // error是增加程序的健壮性,即使有某张图片无法正常加载也不影响后续图片的加载
     $(imgObj).on('load error', function () {
       opts.each && opts.each(count);

       if (count >= len - 1) {
         opts.all && opts.all();
       }
       count++;
     });

     imgObj.src = src;
   });

  };

  // 封装成jQuery插件 有两种方法
  // 1. $.fn.extend -> $('#img').preload() 选中元素后调用
  // 2. $.extend -> $.preload() 可以直接调用
  $.extend({
    preload: function (imgs, opts) {
      new PreLoad(imgs, opts);
    }
  });

})(jQuery);

将图片预加载的逻辑封装成jQuery插件以后,我们就可以直接在代码中调用了,修改后的js代码如下:

var imgs = [
  'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1532191258391&di=a10eff830ac73774f631af907baf3d51&imgtype=0&src=http%3A%2F%2Fimg4.duitang.com%2Fuploads%2Fitem%2F201511%2F19%2F20151119180529_ckQYx.jpeg',
  'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1532192442862&di=39c538bcdd01603d44174ac7197df280&imgtype=jpg&src=http%3A%2F%2Fimg4.imgtn.bdimg.com%2Fit%2Fu%3D4144665989%2C3104020614%26fm%3D214%26gp%3D0.jpg',
  'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1532191258390&di=f68f55ddb98094899a724dc36cade062&imgtype=0&src=http%3A%2F%2F2t.5068.com%2Fuploads%2Fallimg%2F140820%2F39_140820105334_3.jpg',
  'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1532191258387&di=1e1d5c983e4204c6fe4e79424a896d41&imgtype=0&src=http%3A%2F%2Fi1.hdslb.com%2Fbfs%2Farchive%2Fe35d60332d01a70ca2cd1d83a4ac95188464f7db.jpg',
  'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1532191258387&di=41ca4b51770505410e4b776454f485d4&imgtype=0&src=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Farchive%2F70daa8d4db1d31016c4b09f813bca5e71cdf954b.jpg',
  'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1532192495872&di=264c5fc7394abb73dff253aee02f6272&imgtype=0&src=http%3A%2F%2Fimg5.duitang.com%2Fuploads%2Fitem%2F201410%2F01%2F20141001213754_etBCG.jpeg',
  'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1532192657412&di=1b3b6daddda31c05f9bd52cf9f9d16cf&imgtype=jpg&src=http%3A%2F%2Fimg3.imgtn.bdimg.com%2Fit%2Fu%3D2612913783%2C2206253269%26fm%3D214%26gp%3D0.jpg'
];

var index = 0;
    len = imgs.length,
    $progress = $('.progress');

// 图片预加载
$.preload(imgs, {
  // 每一张图片加载完毕后执行
  each: function (count) {
    $progress.html(Math.round((count + 1) / len * 100) + '%');
  },
  // 所有图片加载完毕后执行
  all: function () {
    $('.loading').hide();
    document.title = '1/' + len;
  }
});

$('.btn').on('click', function () {
  if ('prev' === $(this).data('control')) { // 上一张
    index = Math.max(0, --index);
  } else {
    index = Math.min(len - 1, ++index);
  }
  document.title = (index + 1) + '/' + len;
  $('#img').attr('src', imgs[index]);
})

其中$(this).data(‘control’)方法可以获取到元素中以data-开头的自定义属性,此例中获取到的是data-control属性,这一点在实际开发中非常的有用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值