菜单

描绘一个网页进度loading

2018年11月15日 - CSS/CSS3

写一个网页进度loading

2017/02/26 · JavaScript
· 2 评论 ·
Loading

原文出处: jack_lo   

loading随处可见,比如一个app经常会起下拉刷新,上拉加载的成效,在刷新以及加载的经过被为让用户感知到
load
的过程,我们会利用有过渡动画来发表。最普遍的仍“转圈圈”,“省略号”等等。

网页loading有好多所以处,比如页面的加载进度,数据的加载过程等等,数据的加载loading很好做,只需要在加载数据之前(before
ajax)显示loading效果,在数据返回下(ajax
completed)结束loading效果,就得了。

只是页面的加载进度,需要一些技。

页面加载进度一直以来还是一个大面积而以晦涩的求,常见是以它在少数“重”网页(特别是网页打)的行使特别重要性;晦涩是因web的特征,各种零散资源支配其充分为难是“真实”的快,只能是平种“假”的快慢,至少在逻辑代码加载成功前,我们还不能够统计到速度,而逻辑代码自身之速也无能为力统计。另外,我们无可能监控及拥有资源的加载情况。

因此页面的加载进度都是“假”的,它是的目的是为着增强用户体验,使用户不至于在开拓页面后加上日子给一片空白,导致用户流失。

既是“假”的,我们虽使做到“仿真”才起因此。仿真是有含义之,事实上用户并无以乎某平等雕你是未是当真的加载到了百分之几,他但关心你还要load多久。所以接下我们便来贯彻一个页面加载进度loading。

先是准备等同截loading的html:

XHTML

<!DOCTYPE html> <html> <head>
<title>写一个网页进度loading</title> </head>
<body> <div class=”loading” id=”loading”> <div
class=”progress” id=”progress”>0%</div> </div>
</body> </html>

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html>
<head>
    <title>写一个网页进度loading</title>
</head>
<body>
  <div class="loading" id="loading">
    <div class="progress" id="progress">0%</div>
  </div>
</body>
</html>

来点样式装扮一下:

CSS

.loading { display: table; position: fixed; top: 0; left: 0; width:
100%; height: 100%; background-color: #fff; z-index: 5; } .loading
.progress { display: table-cell; vertical-align: middle; text-align:
center; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.loading {
  display: table;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #fff;
  z-index: 5;
}
 
.loading .progress {
  display: table-cell;
  vertical-align: middle;
  text-align: center;
}

我们先假设这个loading只需要在页面加载成功之后隐藏,中间不需展示速度。那么稀粗略,我们第一时间想到的虽是window.onload:

(以下内容为了便利演示,默认使用jQuery,语法有es6的箭头函数)

JavaScript

var $loading = $(‘#loading’) var $progress = $(‘#progress’)
window.onload = () => { $loading.hide() }

1
2
3
4
5
6
var $loading = $(‘#loading’)
var $progress = $(‘#progress’)
 
window.onload = () => {
  $loading.hide()
}

ok,这样中心的loading流程就出矣,我们增加一个快的功效,每隔100ms就自增1,一直顶100%竣工,而一方面window
loaded的下,我们把loading给隐蔽。

咱俩来补一下快:

JavaScript

var $loading = $(‘#loading’) var $progress = $(‘#progress’) var prg =
0 // 初始化进度 var timer = window.setInterval(() => { // 设置定时器
if (prg >= 100) { // 到达终点,关闭定时器 window.clearInterval(timer)
prg = 100 } else { // 未到巅峰,进度自增 prg++ } $progress.html(prg +
‘%’) console.log(prg) }, 100) window.onload = () => { $loading.hide()
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var $loading = $(‘#loading’)
var $progress = $(‘#progress’)
var prg = 0  // 初始化进度
 
var timer = window.setInterval(() => {  // 设置定时器
  if (prg >= 100) {  // 到达终点,关闭定时器
    window.clearInterval(timer)
    prg = 100
  } else {  // 未到终点,进度自增
    prg++
  }
 
  $progress.html(prg + ‘%’)
  console.log(prg)
}, 100)
 
window.onload = () => {
  $loading.hide()
}

效能是,但是发生个问题,万一window
loaded太慢了,导致进度显示load到100%了,loading还并未藏身,那就是起脸了。所以,我们要给loading在window
loaded的时段才抵达极限,在就之前,loading可以保障一个等待的状态,比如在80%的时刻,先住一止,然后于loaded的早晚快将速推进到100%。这个做法是眼下绝大部客进度条之做法。

JavaScript

var $loading = $(‘#loading’) var $progress = $(‘#progress’) var prg =
0 var timer = window.setInterval(() => { if (prg >= 80) { //
到达第一品80%,关闭定时器,保持等 window.clearInterval(timer) prg =
100 } else { prg++ } $progress.html(prg + ‘%’) console.log(prg) }, 100)
window.onload = () => { window.clearInterval(timer)
window.setInterval(() => { if (prg >= 100) { //
到达顶峰,关闭定时器 window.clearInterval(timer) prg = 100
$loading.hide() } else { prg++ } $progress.html(prg + ‘%’)
console.log(prg) }, 10) // 时间间隔缩短 }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var $loading = $(‘#loading’)
var $progress = $(‘#progress’)
var prg = 0
 
var timer = window.setInterval(() => {
  if (prg >= 80) {  // 到达第一阶段80%,关闭定时器,保持等待
    window.clearInterval(timer)
    prg = 100
  } else {
    prg++
  }
 
  $progress.html(prg + ‘%’)
  console.log(prg)
}, 100)
 
window.onload = () => {
  window.clearInterval(timer)
  window.setInterval(() => {
    if (prg >= 100) {  // 到达终点,关闭定时器
      window.clearInterval(timer)
      prg = 100
      $loading.hide()
    } else {
      prg++
    }
 
    $progress.html(prg + ‘%’)
    console.log(prg)
  }, 10)  // 时间间隔缩短
}

ok,这基本上就是咱怀念如果的功用了,我们来提炼一下代码,把再的代码给封装一下:

JavaScript

var $loading = $(‘#loading’) var $progress = $(‘#progress’) var prg =
0 var timer = 0 progress(80, 100) window.onload = () => {
progress(100, 10, () => { $loading.hide() }) } function progress
(dist, delay, callback) { window.clearInterval(timer) timer =
window.setInterval(() => { if (prg >= dist) {
window.clearInterval(timer) prg = dist callback && callback() } else {
prg++ } $progress.html(prg + ‘%’) console.log(prg) }, delay) }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var $loading = $(‘#loading’)
var $progress = $(‘#progress’)
var prg = 0
 
var timer = 0
 
progress(80, 100)
 
window.onload = () => {
  progress(100, 10, () => {
    $loading.hide()
  })
}
 
function progress (dist, delay, callback) {
  window.clearInterval(timer)
  timer = window.setInterval(() => {
    if (prg >= dist) {
      window.clearInterval(timer)
      prg = dist
      callback && callback()
    } else {
      prg++
    }
 
    $progress.html(prg + ‘%’)
    console.log(prg)
  }, delay)
}

咱取得了一个progress函数,这个函数就是咱要的功能模块,通过传播一个靶价、一个时日距离,就可如法炮制进度的演化过程。

当下来拘禁,这个速度还是稍稍问题之:

  1. 快太平均,相同之辰间隔,相同的增量,不适合网络环境之表征;
  2. window.onload太抢,我们还不及看清100%,loading就已经丢失了;
  3. 每次第一品都是于80%即便暂停了,露馅儿了;

首先单点,我们只要叫日间隔随机,增量为随便;第二独点十分简单,我们延缓一下纵吓了;第三沾吧得我们随便产生一个初始值。

增量随机大好惩治,如何被时间距离随机?setInterval是力不从心动态设置delay的,那么我们就是设管其改造一下,使用setTimeout来落实。(setInterval跟setTimeout的用法及区分就是不细致说了吧?)

JavaScript

var $loading = $(‘#loading’) var $progress = $(‘#progress’) var prg =
0 var timer = 0 progress([80, 90], [1, 3], 100) //
使用数组来代表以机数的区间 window.onload = () => { progress(100, [1,
5], 10, () => { window.setTimeout(() => { //
延迟了扳平秒再隐藏loading $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) + ‘%’) //
留意,由于已经休是自增1,所以这边而取整 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 } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
var $loading = $(‘#loading’)
var $progress = $(‘#progress’)
var prg = 0
 
var timer = 0
 
progress([80, 90], [1, 3], 100)  // 使用数组来表示随机数的区间
 
window.onload = () => {
  progress(100, [1, 5], 10, () => {
    window.setTimeout(() => {  // 延迟了一秒再隐藏loading
      $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) + ‘%’)  // 留意,由于已经不是自增1,所以这里要取整
    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
  }
}

由来,我们差不多得了急需。

but,还有一个比隐蔽的题材,我们本动window.onload,发现从进页面,到window.onload这中间相隔时间很缺少,我们着力是感受不顶第一等速度(80%)的,这是绝非问题之——我们注意的凡,如果页面的加载资源数量众多,体积十分充分的时刻,从进来页面,到window.onload就非是这么快了,这中间或会见大老(5~20秒不等),但实际,我们只需要吗
首屏资源
的加载争取时间就好了,不待等所有资源就绪,而且又快地呈现页面吗是增长用户体验的重要性。

俺们该考虑页面loading停留过久的情,我们要呢loading设置一个逾期时间,超过这时刻,假设window.onload还尚未水到渠成,我们啊要拿速度推进到100%,把loading结束掉。

JavaScript

var $loading = $(‘#loading’) var $progress = $(‘#progress’) var prg =
0 var timer = 0 progress([80, 90], [1, 3], 100) //
使用数组来表示仍机数的间距 window.onload = () => { progress(100, [1,
5], 10, () => { window.setTimeout(() => { //
延迟了平等秒再隐藏loading $loading.hide() }, 1000) }) }
window.setTimeout(() => { // 设置5秒的晚点时间 progress(100, [1,
5], 10, () => { window.setTimeout(() => { //
延迟了同秒再隐藏loading $loading.hide() }, 1000) }) }, 5000) 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
var $loading = $(‘#loading’)
var $progress = $(‘#progress’)
var prg = 0
 
var timer = 0
 
progress([80, 90], [1, 3], 100)  // 使用数组来表示随机数的区间
 
window.onload = () => {
  progress(100, [1, 5], 10, () => {
    window.setTimeout(() => {  // 延迟了一秒再隐藏loading
      $loading.hide()
    }, 1000)
  })
}
 
window.setTimeout(() => {  // 设置5秒的超时时间
  progress(100, [1, 5], 10, () => {
    window.setTimeout(() => {  // 延迟了一秒再隐藏loading
      $loading.hide()
    }, 1000)
  })
}, 5000)
 
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) + ‘%’)  // 留意,由于已经不是自增1,所以这里要取整
    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
  }
}

咱俩一直装了一个定时器,5s之岁月来当超时时间。这样做是足以的。

but,还是时有发生问题,这个定时器是于js加载完毕之后才起生效的,也就是说,我们忽略了js加载完毕前的光阴,这误差可充分而稍许,我们设置的5s,实际用户或等待了8s,这是发出问题之。我们举行用户体验,需要从事实上情形去考虑,所以这起日还索要重提前有,我们以head里来记录是初步日,然后于js当中去开比,如果日各异大于超时时间,那我们就是可以直接执行最后之得步骤,如果低于超时时间,则等待
剩下的工夫 过后,再好速度。

事先以head里埋点,记录用户进入页面的时光loadingStartTime

XHTML

<!DOCTYPE html> <html> <head>
<title>写一个网页进度loading</title> <script>
window.loadingStartTime = new Date() </script> <script
src=”index.js”></script> </head> <body> <div
class=”loading” id=”loading”> <div class=”progress”
id=”progress”>0%</div> </div> </body> </html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html>
<head>
  <title>写一个网页进度loading</title>
  <script>
    window.loadingStartTime = new Date()
  </script>
  <script src="index.js"></script>
</head>
<body>
  <div class="loading" id="loading">
    <div class="progress" id="progress">0%</div>
  </div>
</body>
</html>

然后,我们本着比 目前的工夫
,看是不是过期:(为了便利复用代码,我拿成功的片段封装成函数complete)

JavaScript

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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. 咱们得一个可知给我们总计增量的变量next
  2. 是因为我们的progress犹是传目的速度的,我们得另外一个函数add,来传增量进度。

JavaScript

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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

上述,就是咱们一步步贯彻一个进度loading的历程了,演示代码可以通我的codePen
写一个网页进度loading。

类很简单的一个效,其实仔细琢磨,还是出成百上千细节要考虑的。

顶这里,其实诚已做到了,代码有点多发生硌乱是无是?你得整理一下,封装成为插件的。

只是,好吧,其实我曾将这速度封装成插件了。。。

没错,其实自己就是是来援助团结打广告之。。。

吓吧,github仓库在此
ez-progress。

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

JavaScript

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]) // 飞一般地冲向终点 }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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])  // 飞一般地冲向终点
}

木油错,94这样简单!

马上也许是自我眼前描绘过最缺的博文了,由此观以前是出多么的啰嗦,哈哈哈哈!

1 赞 13 收藏 2
评论

图片 1

(以下内容为了便利演示,默认使用jQuery,语法有es6的箭头函数)

来点样式装扮一下:

俺们这边为了有利于,用setTimeout来学图的加载,真实应用该是采取image.onload

效益不错,但是发生个问题,万一window
loaded太慢了,导致进度显示load到100%了,loading还并未藏身,那就起脸了。所以,我们要给loading在window
loaded的时段才到终点,在就之前,loading可以保障一个等待的状态,比如当80%之时刻,先住一止,然后以loaded的早晚快将速推进到100%。这个做法是眼下绝大部份进度条之做法。

率先只点,我们而给岁月距离随机,增量为随机;第二个点老简单,我们延缓一下即便吓了;第三沾呢亟需我们随便产生一个初始值。

俺们一直设置了一个定时器,5s之日子来作超时时间。这样做是足以的。

ok,这基本上就是是咱们怀念如果的效能了,我们来提炼一下代码,把更的代码给封装一下:

不过,事情还未曾截止,少年你最天真。

先以head里埋点,记录用户进入页面的时空loadingStartTime

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])  // 飞一般地冲向终点
}
var $loading = $('#loading')
var $progress = $('#progress')
var prg = 0

var timer = 0

progress(80, 100)

window.onload = () => {
  progress(100, 10, () => {
    $loading.hide()
  })
}

function progress (dist, delay, callback) {
  window.clearInterval(timer)
  timer = window.setInterval(() => {
    if (prg >= dist) {
      window.clearInterval(timer)
      prg = dist
      callback && callback()
    } else {
      prg++
    }

    $progress.html(prg + '%')
    console.log(prg)
  }, delay)
}

but,还有一个于隐蔽之题目,我们现在应用window.onload,发现从进页面,到window.onload这中相隔时间老缺乏,我们基本是感受不交第一级速度(80%)的,这是不曾问题的——我们注意的是,如果页面的加载资源数量众多,体积大酷之上,从进来页面,到window.onload就不是这样迅速了,这中可能会见好老(5~20秒不等),但骨子里,我们只有待也
首屏资源
的加载争取时间就好了,不欲拭目以待所有资源就绪,而且又快地呈现页面也是增强用户体验的主要。

立刻三摆图要霸占20% + 25% + 30% = 75%的进度。

loading随处可见,比如一个app经常会面时有发生下拉刷新,上拉加载的功能,在刷新以及加载的进程遭到为吃用户感知到
load
的长河,我们见面用一些连着动画来表达。最广泛的按“转圈圈”,“省略号”等等。

然,好吧,其实自己都把这个速度封装成插件了。。。

var $loading = $('#loading')
var $progress = $('#progress')
var prg = 0

var timer = 0

progress([80, 90], [1, 3], 100)  // 使用数组来表示随机数的区间

window.onload = () => {
  progress(100, [1, 5], 10, () => {
    window.setTimeout(() => {  // 延迟了一秒再隐藏loading
      $loading.hide()
    }, 1000)
  })
}

window.setTimeout(() => {  // 设置5秒的超时时间
  progress(100, [1, 5], 10, () => {
    window.setTimeout(() => {  // 延迟了一秒再隐藏loading
      $loading.hide()
    }, 1000)
  })
}, 5000)

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) + '%')  // 留意,由于已经不是自增1,所以这里要取整
    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
  }
}

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

唯独页面的加载进度,需要或多或少技艺。

ok,这样基本的loading流程就闹了,我们增加一个快的功用,每隔100ms就自增1,一直到100%了却,而另一方面window
loaded的上,我们将loading给隐蔽。

var $loading = $('#loading')
var $progress = $('#progress')

window.onload = () => {
  $loading.hide()
}

接下来,我们对比 手上底时空
,看是不是过期:(为了方便复用代码,我将成功的组成部分封装成函数complete)

俺们先假设这个loading只需要在页面加载成功之后隐藏,中间不需出示速度。那么深简单,我们第一时间想到的就是window.onload:

先是准备同截loading的html:

这也许是本身时形容过太差的博文了,由此看出以前是来多么的啰嗦,哈哈哈哈!

咱俩理应考虑页面loading停留过久的状,我们得吗loading设置一个过期时间,超过此日子,假设window.onload还并未就,我们为使管速度推进到100%,把loading结束掉。

好吧,github仓库在此
ez-progress。

迄今为止,我们算完整地落实了即无异成效。

.loading {
  display: table;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #fff;
  z-index: 5;
}

.loading .progress {
  display: table-cell;
  vertical-align: middle;
  text-align: center;
}

页面加载进度一直以来都是一个宽广而与此同时晦涩的需,常见是盖她于一些“重”网页(特别是网页游戏)的应用特别重大;晦涩是为web的特性,各种零散资源支配它好不便是“真实”的进度,只能是一样种“假”的速度,至少在逻辑代码加载成功之前,我们还不能够统计到快,而逻辑代码自身的快慢也无从统计。另外,我们无可能监控及所有资源的加载情况。

问题是,如果图片加载成功是按照顺序来之,那我们得以挺简短地:10(假设初始进度是10%)
-> 30 -> 55 -> 85 ->
100,但实际是,图片未会见随顺序来,谁早到谁晚至是说不准的,所以我们需要重合理的法去管理这些进度增量,使其不见面相覆盖。

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

假使目的是为写一个纯障眼法的伪loading,那与其它loading的贯彻即无什么界别了,我们工作讲究脚踏实地,能促成的实现,不克实现的,为了组织协调,我们不得已坑蒙拐骗。那么我们还能够重接近实际情形一点吧?其实是好的。

咱来分析一个状况,假要我们怀念被咱的loading更加实事求是一些,那么我们可选择性地对页面上几个比较坏之资源的加载进行跟踪,然后拆分整个快长条,比如我们页面有三张大图a、b、c,那么我们拿速条拆成五段子,每加载了一布置图我们不怕推动一个速度:

类很简短的一个效,其实仔细斟酌,还是来成百上千细节要考虑的。

增量随机大好惩治,如何为岁月距离随机?setInterval是心有余而力不足动态设置delay的,那么我们就如管其改造一下,使用setTimeout来兑现。(setInterval跟setTimeout的用法及界别就是不细瞧说了咔嚓?)

俺们来补偿一下快:

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
  }
}
var $loading = $('#loading')
var $progress = $('#progress')
var prg = 0

var timer = window.setInterval(() => {
  if (prg >= 80) {  // 到达第一阶段80%,关闭定时器,保持等待
    window.clearInterval(timer)
    prg = 100
  } else {
    prg++
  }

  $progress.html(prg + '%')
  console.log(prg)
}, 100)

window.onload = () => {
  window.clearInterval(timer)
  window.setInterval(() => {
    if (prg >= 100) {  // 到达终点,关闭定时器
      window.clearInterval(timer)
      prg = 100
      $loading.hide()
    } else {
      prg++
    }

    $progress.html(prg + '%')
    console.log(prg)
  }, 10)  // 时间间隔缩短
}

木油错,94这么简单!

至此,我们差不多就了需求。

眼前来拘禁,这个速度还是聊题目的:

<!DOCTYPE html>
<html>
<head>
  <title>写一个网页进度loading</title>
  <script>
    window.loadingStartTime = new Date()
  </script>
  <script src="index.js"></script>
</head>
<body>
  <div class="loading" id="loading">
    <div class="progress" id="progress">0%</div>
  </div>
</body>
</html>
var $loading = $('#loading')
var $progress = $('#progress')
var prg = 0  // 初始化进度

var timer = window.setInterval(() => {  // 设置定时器
  if (prg >= 100) {  // 到达终点,关闭定时器
    window.clearInterval(timer)
    prg = 100
  } else {  // 未到终点,进度自增
    prg++
  }

  $progress.html(prg + '%')
  console.log(prg)
}, 100)

window.onload = () => {
  $loading.hide()
}

but,还是有题目,这个定时器是在js加载完毕之后才起来生效之,也就是说,我们忽视了js加载完毕前的时刻,这误差可大而是有些,我们设置的5s,实际用户或等待了8s,这是起问题的。我们开用户体验,需要从实际上情况去考虑,所以这开始日还得重新提前有,我们于head里来记录者开时间,然后在js当中去开比,如果时光不一大于超时时间,那我们即便得一直实施最后之形成步骤,如果低于超时时间,则等待
结余的时空 过后,再好速度。

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
  }
}

从而页面的加载进度都是“假”的,它是的目的是为了增强用户体验,使用户不至于在打开页面后加上日子对一片空白,导致用户流失。

俺们获取了一个progress函数,这个函数就是我们着重的功能模块,通过传播一个目标价、一个时空间隔,就足以如法炮制进度的演化过程。

<!DOCTYPE html>
<html>
<head>
    <title>写一个网页进度loading</title>
</head>
<body>
  <div class="loading" id="loading">
    <div class="progress" id="progress">0%</div>
  </div>
</body>
</html>

既然如此是“假”的,我们尽管假设成功“仿真”才起因此。仿真是有含义之,事实上用户并无在乎某平等雕你是勿是真正的加载到了百分之几,他但关心你还要load多久。所以接下我们就是来贯彻一个页面加载进度loading。

var $loading = $('#loading')
var $progress = $('#progress')
var prg = 0

var timer = 0

progress([80, 90], [1, 3], 100)  // 使用数组来表示随机数的区间

window.onload = () => {
  progress(100, [1, 5], 10, () => {
    window.setTimeout(() => {  // 延迟了一秒再隐藏loading
      $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) + '%')  // 留意,由于已经不是自增1,所以这里要取整
    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
  }
}

到此,其实确实都到位了,代码有点多生硌乱是勿是?你可整理一下,封装成为插件的。

  1. 速度太平均,相同之时空间隔,相同的增量,不符合网络环境之特性;
  2. window.onload太抢,我们还不及看清100%,loading就曾少了;
  3. 历次第一路都是以80%虽搁浅了,露馅儿了;
  1. 咱们要一个能为我们总共增量的变量next
  2. 出于我们的progress且是传目的速度的,我们需要另外一个函数add,来传增量进度。

不错,其实我就算是来拉团结从广告的。。。

以上,就是咱一步步贯彻一个快loading的经过了,演示代码可以穿我的codePen
描绘一个网页进度loading。

网页loading有许多就此处,比如页面的加载进度,数据的加载过程等等,数据的加载loading很好做,只需要在加载数据之前(before
ajax)显示loading效果,在数码返回后(ajax
completed)结束loading效果,就得了。

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图