javascript实现一个网页加载进度loading(3)

var $loading = $('#loading') var $progress = $('#progress') var prg = 0 var timer = 0 var now = new Date() // 记录当前时间 var timeout = 5000 // 超时时间 progress([80, 90], [1, 3], 100) window.onload = () => { complete() } if (now - loadingStartTime > timeout) { // 超时 complete() } else { window.setTimeout(() => { // 未超时,则等待剩余时间 complete() }, timeout - (now - loadingStartTime)) } function complete () { // 封装完成进度功能 progress(100, [1, 5], 10, () => { window.setTimeout(() => { $loading.hide() }, 1000) }) } function progress (dist, speed, delay, callback) { var _dist = random(dist) var _delay = random(delay) var _speed = random(speed) window.clearTimeout(timer) timer = window.setTimeout(() => { if (prg + _speed >= _dist) { window.clearTimeout(timer) prg = _dist callback && callback() } else { prg += _speed progress (_dist, speed, delay, callback) } $progress.html(parseInt(prg) + '%') console.log(prg) }, _delay) } function random (n) { if (typeof n === 'object') { var times = n[1] - n[0] var offset = n[0] return Math.random() * times + offset } else { return n } }

至此,我们算是完整地实现了这一功能。

然而,事情还没有结束,少年你太天真。

如果目的是为了写一个纯粹障眼法的伪loading,那跟其他loading的实现就没什么区别了,我们做事讲究脚踏实地,能实现的实现,不能实现的,为了团队和谐,我们不得已坑蒙拐骗。那么我们还能更贴近实际情况一点吗?其实是可以的。

我们来分析一个场景,假设我们想让我们的loading更加真实一些,那么我们可以选择性地对页面上几个比较大的资源的加载进行跟踪,然后拆分整个进度条,比如我们页面有三张大图a、b、c,那么我们将进度条拆成五段,每加载完一张图我们就推进一个进度:

随机初始化[10, 20] ->
图a推进20%的进度 ->
图b推进25%的进度 ->
图c推进30%的进度 ->
完成100%

这三张图要占20% + 25% + 30% = 75%的进度。

问题是,如果图片加载完成是按照顺序来的,那我们可以很简单地:10(假设初始进度是10%) -> 30 -> 55 -> 85 -> 100,但事实是,图片不会按照顺序来,谁早到谁晚到是说不准的,所以我们需要更合理的方式去管理这些进度增量,使它们不会互相覆盖。

  1.0、我们需要一个能够替我们累计增量的变量next;

  2.0、由于我们的progress都是传目的进度的,我们需要另外一个函数add,来传增量进度。

var $loading = $('#loading') var $progress = $('#progress') var prg = 0 var timer = 0 var now = new Date() var timeout = 5000 var next = prg add([30, 50], [1, 3], 100) // 第一阶段 window.setTimeout(() => { // 模拟图a加载完 add(20, [1, 3], 200) }, 1000) window.setTimeout(() => { // 模拟图c加载完 add(30, [1, 3], 200) }, 2000) window.setTimeout(() => { // 模拟图b加载完 add(25, [1, 3], 200) }, 2500) window.onload = () => { complete() } if (now - loadingStartTime > timeout) { complete() } else { window.setTimeout(() => { complete() }, timeout - (now - loadingStartTime)) } function complete () { add(100, [1, 5], 10, () => { window.setTimeout(() => { $loading.hide() }, 1000) }) } function add (dist, speed, delay, callback) { var _dist = random(dist) if (next + _dist > 100) { // 对超出部分裁剪对齐 next = 100 } else { next += _dist } progress(next, speed, delay, callback) } function progress (dist, speed, delay, callback) { var _delay = random(delay) var _speed = random(speed) window.clearTimeout(timer) timer = window.setTimeout(() => { if (prg + _speed >= dist) { window.clearTimeout(timer) prg = dist callback && callback() } else { prg += _speed progress (dist, speed, delay, callback) } $progress.html(parseInt(prg) + '%') console.log(prg) }, _delay) } function random (n) { if (typeof n === 'object') { var times = n[1] - n[0] var offset = n[0] return Math.random() * times + offset } else { return n } }

我们这里为了方便,用setTimeout来模拟图片的加载,真实应用应该是使用image.onload。

接下来整理一下有点乱的代码,封装成一个插件,下载地址为:

ez-progress 是一个web(伪)进度插件,使用 ez-progress 实现这个功能非常简单:

var Progress = require('ez-progress') var prg = new Progress() var $loading = $('#loading') var $progress = $('#progress') prg.on('progress', function (res) { var progress = parseInt(res.progress) // 注意进度取整,不然有可能会出现小数 $progress.html(progress + '%') }) prg.go([60, 70], function (res) { prg.complete(null, [0, 5], [0, 50]) // 飞一般地冲向终点 }, [0, 3], [0, 200]) window.onload = function () { prg.complete(null, [0, 5], [0, 50]) // 飞一般地冲向终点 }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwjzxg.html