当前位置: 永利皇宫463手机版 > Web前端 > 正文

写五个网页进度loading

时间:2019-11-28 12:19来源:Web前端
写一个网页进度loading 2017/02/26 · JavaScript· 2 评论 ·Loading 原文出处: jack_lo    loading随处可见,比如一个app经常会有下拉刷新,上拉加载的功能,在刷新和加载的过程中为了让用户感知

写一个网页进度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

  • _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]永利皇宫463娱乐网址, 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
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

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

  • _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 } }
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 评论

永利皇宫463娱乐网址 1

复制代码 代码如下:

(function($) {
(function($) {
$.preload = function(data, cfg) {
return new Loader(data, cfg);
};
var maps = {}, on = $.event.add, un = $.event.remove, head = document.getElementsByTagName('head')[0], body =
document.body, bs = $.browser, ie = bs.msie, webkit = bs.webkit, gecko = bs.mozilla, space = 1000, ajax =
$.ajax,
loaders = $.preload.loaders = {
'js' : function(url, callback, timeout, defer) {
var s, timer;
if (defer) {
if (ie) {
return loaders.img(url, callback, timeout);
} else {
s = document.createElement('object');
s.data = url;
s.width = s.height = 0;
}
} else {
s = document.createElement('script');
s.setAttribute('type', 'text/javascript');
s.setAttribute('src', url);
}
function f() {
if (timer)
clearTimeout(timer);
s.onreadystatechange = s.onload = s.onerror = null;
callback(url, false);
}
if (ie) {
s.onreadystatechange = function() {
if (this.readyState === 'loaded' || this.readyState === 'complete') {
if (timer)
clearTimeout(timer);
s.onreadystatechange = null;
callback(url, true);
}
};
} else {
s.onload = function() {
if (timer)
clearTimeout(timer);
s.onload = s.onerror = null;
callback(url, true);
};
s.onerror = f;
}
timer = setTimeout(f, timeout);
body.appendChild(s);
},
'css' : function(url, callback, timeout, defer) {
if (defer) {
return loaders.js(url, callback, timeout, defer);
}
var s = document.createElement('link'), timer;
s.setAttribute('rel', 'stylesheet');
s.setAttribute('type', 'text/css');
s.setAttribute('href', url);
function f() {
if (timer)
clearTimeout(timer);
s.onreadystatechange = s.onload = s.onerror = null;
callback(url, false);
}
if (ie) {
s.onreadystatechange = function() {
if (this.readyState === 'loaded' || this.readyState === 'complete') {
if (timer)
clearTimeout(timer);
s.onreadystatechange = null;
callback(url, true);
}
};
timer = setTimeout(f, timeout);
} else if (webkit || gecko) {
timer = new Date();
function f() {
if (('sheet' in s) && ('cssRules' in s.sheet)) {
try {
callback(url, !!s.sheet.cssRules[0]);
} catch (e) {
setTimeout(f, space);
}
} else if (new Date() - timer > timeout) {
callback(url, false);
} else {
setTimeout(f, space);
}
}
setTimeout(f, space * 2);
} else {
s.onload = function() {
if (timer)
clearTimeout(timer);
s.onload = s.onerror = null;
callback(url, true);
};
s.onerror = f;
timer = setTimeout(f, timeout);
}
head.appendChild(s);
},
'img' : function(url, callback, timeout) {
var s = new Image(), timer;
function f() {
if (timer)
clearTimeout(timer);
s.onload = s.onerror = null;
callback(url, false);
}
s.onload = function() {
if (timer)
clearTimeout(timer);
s.onload = s.onerror = null;
callback(url, true);
};
s.onerror = f;
timer = setTimeout(f, timeout);
s.src = url;
},
'ajax' : function(url, callback, cfg) {
cfg = cfg || {};
cfg.url = url;
cfg.success = function(data) {
callback(url, true, data);
};
cfg.error = function() {
callback(url, false);
};
ajax(cfg);
}
};
function Loader(data, cfg) {
var self = this, cur = -1, items = [], pendings = [], done, i = 0, l = data.length, j, m, s, t, c, d, tt, item, doing =
0, load;
cfg = cfg || {};
for (; i < l; ++i) {
item = data[i];
if (typeof item === 'string') {
s = item.substr(item.lastIndexOf('.') + 1);
items.push(maps[item] = {
type : loaders[s] ? s : 'img',
url : item
});
} else if (item.urls) {
for (j = 0, s = item.type, t = item.require, c = item.callback, d = item.defer, tt = item.timeout, item =
item.urls, m = item.length; j < m; ++j) {
s = s || item[j].substr(item[j].lastIndexOf('.') + 1);
items.push(maps[item[j]] = {
type : loaders[s] ? s : 'img',
url : item[j],
require : t,
callback : c,
defer : d,
timeout : tt
});
}
} else {
if (!item.type) {
s = item.url.substr(item.url.lastIndexOf('.') + 1);
item.type = loaders[s] ? s : 'img';
}
items.push(maps[item.url] = item);
}
}
this.success = this.fail = this.progress = 0;
if (cfg.onFinish)
this.onFinish = cfg.onFinish;
timeout = cfg.timeout || 2000;
function callback(url, flag, data) {
if (flag) {
++self.success;
} else {
++self.fail;
}
self.progress = (self.success + self.fail) / items.length;
console.info(url);
console.warn(flag);
item = maps[url];
item.success = flag;
if (self.progress === 1) {
self.stop();
}
if (item.parent && !item.defer && !cfg.defer) {
$(item.parent)[0].innerHTML = data || '';
}
if (item.callback) {
item.callback(data);
}
item.done = true;
--doing;
}
function runnable(item, pend) {
var it;
if (typeof item.require === 'string') {
if (item.done)
return false;
if (!item.require)
return true;
it = maps[item.require];
if (!it || it.done) {
if (pend)
pendings.shift();
if (it && it.success) {
return true;
} else {
callback(item.url, false);
}
} else if (!pend) {
pendings.push(item);
}
} else {
for (it = item.length; it--;) {
if (!runnable(item[it], pend))
return false;
}
return true;
}
}
function run() {
var item = pendings[0];
if (!item || !runnable(item, true)) {
while (item = items[++cur]) {
if (runnable(item)) {
break;
}
}
}
if (item) {
var fn = loaders[item.type || 'img'];
if (fn) {
++doing;
if (item.type === 'ajax') {
if (item.cfg && !item.cfg.timeout)
item.cfg.timeout = timeout;
fn(item.url, callback, item.cfg);
} else {
fn(item.url, callback, item.timeout || timeout, item.defer === undefined ? cfg.defer
: item.defer);
}
};
if (load) {
run();
} else {
self.timer = setTimeout(run, space);
}
} else if (pendings.length) {
self.timer = setTimeout(run, space);
}
}
this.start = function(delay) {
if (!done)
this.timer = setTimeout(run, delay > space ? delay : space);
};
this.stop = function() {
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
done = true;
if (this.onFinish) {
if (!doing)
this.onFinish();
else {
s = setInterval(function() {
if (!doing) {
clearInterval(s);
self.onFinish();
}
}, space);
}
}
}
};
this.pause = function() {
clearTimeout(this.timer);
};
this.resume = function() {
this.timer = setTimeout(run, space);
};
this.load = function() {
clearTimeout(this.timer);
load = true;
run();
};
}
})(jQuery);
/**
* @example
* var loader = $.preload([
// 字符串,采用默认配置
'1.jpg', '1.js',
// 对象,自定义配置,如type, require, timeout, defer, callback
{
type : 'img',
url : '',
timeout : 10
}, {
url : '3.js',
callback : fn,
defer : true,
require : '1.js'
},
// 对象,可用urls指定一组相同配置
{
type : 'css',
urls : ['4.css', '5.css']
}], {
// 加载结束后调用
onFinish : fn,
// 加载超时
timeout : 50
});
// 开始预加载
loader.start();
loader.stop();
// 暂停预加载
loader.pause();
loader.resume();
// 实时加载
loader.load();
*/

代码如下: (function($) { (function($) { $.preload = function(data, cfg) { return new Loader(data, cfg); }; var maps = {}, on = $.event.add, un = $.event.remove, he...

编辑:Web前端 本文来源:写五个网页进度loading

关键词: