网站预加载进度条的实现
我们经常会看到,一些站点在首次进入的时候会先显示一个进度条,等资源加载完毕后再呈现页面,大概像这样:
然后整个页面的操作就会非常流畅,因为之后没必要再等待加载资源了。尤其是在移动端,或者是页游中,这样做能避免页面出现白屏(等待加载图片),很大程度提升用户体验。那这种技术是如何实现的呢?其实非常简单,本文就来从基础细节探究一番。
为什么需要资源预加载
大多时候,我们的页面并不是一次渲染完毕的,而是随着用户的操作,不断修改DOM节点,如果你动态插入了一个图片节点,那么浏览器要马上发一个http请求,把图片加载下来然后渲染在页面上,如果用户此时的网速不佳,那么加载这张图片可能就会消耗几秒钟时间,此时页面上什么都没有(白屏)。最坏的情况,如果你的应用图片很多,半天加载不出几张图,用户很可能就在白屏的那几秒跳走了。在游戏中更严重,主角的图片如果加载不出来,让用户玩空气去?
除了在DOM中插入图片节点,其他凡是涉及到要展示一张新图片的操作,浏览器都得即时去请求图片。比如,为某个节点添加如下css类来增加背景图片:
1.
.bg1{
2.
background: url(http:
//p2.qhimg.com/t01ed1438874f940dc0.jpg);
3.
}
或者是动态修改了src属性、在canvas绘制图片等,这些都会即时请求新资源。
那么,资源预加载为什么能解决上述问题呢?
我们预加载的资源,浏览器会缓存下来,再次使用的时候,浏览器会检查是不是已经在缓存中,如果在,则直接用缓存的资源,不发送请求,或者由服务端返回304 not modified(304只带请求头信息,不传输资源)。这样使用一张图片的时间会大大缩减,我们的页面看起来会非常流畅,妈妈再也不用担心用户会跳走了~
也就是说,预加载的资源我们并不需要手动保存,由浏览器自动放到缓存了。
资源预加载的场景
什么样的项目需要预加载资源呢?
范围应该锁定单页面应用,SPA的视图一般都是一步一步来呈现的,各种资源通过异步请求来获取,为了追求原生app般的流畅体验,可以把一些资源预加载下来。当然对于一些业务相关的图片资源,也可考虑延迟加载,但延迟加载不是本文讨论的范畴。
视图/图片较多的专题页面,或者是需要逐帧图片来完成的动画效果,最好都要做预加载。
HTML5游戏,图片一般都比较多,而且很多逐帧动画,必须要预加载,事实上一些游戏引擎都会提供相应功能。
哪些资源需要预加载呢?
web中包含的资源有很多种,图片、音视频之类的媒体文件,另外就是js、css文件,这些都需要发送请求来获取。那这些资源难道我们都预加载?
当然不是了,预加载也是需要消耗时间的,总不能让用户等你加载个几十秒钟吧。具体预加载哪些资源,需要基于具体的考虑,也跟你的项目相关。以下是一些我的想法:
js、css文件不需进行预加载。现在写js基本都用requirejs之类的加载器,而且最后都会进行压缩合并,将请求数降到最低,最终只有一个文件,有些团队甚至还将压缩后的代码直接放在行内,这样一个多余的请求都没有了。
那么需要预加载的就是媒体文件了,图片、音视频之类。这类资源也得根据实际情况来选择哪些需要预加载。比如大多数页面装饰性图片就需要预加载,而由业务动态获取的图片则无法预加载(预先不知道地址)。用作音效、小动画的音视频可以预加载,一个半小时长的视频就不能预加载了。
预加载的原理与加载进度的获取
上面都是纸上谈兵的一些观点,下面我们该从技术的角度来思考一下预加载该如何实现。
原理其实也相当简单,就是维护一个资源列表,挨个去加载列表中的资源,然后在每个资源加载完成的回调函数中更新进度即可。
以图片为例,大致的代码应该是这样:
1.
var image =
new
Image();
2.
image.onload = function(){};
3.
image.onerror = function(){};
4.
image.src = url;
这样就OK啦,图片已经进缓存,留着以后使用吧。
再说进度,这个进度严格来讲并不是文件加载的实时进度,因为我们只能在每个文件加载完成的时候执行回调,无法像timeline中那样拿到文件加载的实时进度。
计算方法就很简单了,当前加载完的资源个数/资源总数*100,就是加载进度的百分比了。
资源预加载小插件:resLoader.js介绍
本文的重点终于来了。。。额
根据上面的原理,我写了一个插件,用来做资源预加载。
具备的特征如下:
1. 自定义资源列表,用于预加载
2. 自定义onProgress,想展示成进度条还是百分比数字还是个性的设计都可
3. 开始和结束可配置回调函数
4. 只支持图片的预加载
5. 支持amd、cmd加载器加载,同时支持直接用<script>标签引入使用
6. 不依赖其他库
用法如下:
01.
var loader =
new
resLoader({
02.
resources : [
03.
'http://p2.qhimg.com/t01ed1438874f940dc0.jpg'
,
04.
'http://p9.qhimg.com/t01b4ff03b72c7dc6c7.jpg'
,
05.
'http://p2.qhimg.com/t01dd90dfbec92074d0.jpg'
,
06.
'http://p7.qhimg.com/t01cfec6d87cde457c5.jpg'
,
07.
'http://p9.qhimg.com/t01943ced462da67833.jpg'
,
08.
'http://p0.qhimg.com/t01943ced462da67833.jpg'
,
09.
'http://p6.qhimg.com/t01aa15a7ba7ccb49a7.jpg'
,
10.
'http://p8.qhimg.com/t010f1e8badf1134376.jpg'
,
11.
'http://p8.qhimg.com/t01cf37ea915533a032.jpg'
,
12.
'http://p3.qhimg.com/t0193d8a3963e1803e9.jpg'
,
13.
'http://p3.qhimg.com/t01cd6a4d4b4bd4457b.jpg'
14.
],
15.
onStart : function(total){
16.
console.log(
'start:'
+total);
17.
},
18.
onProgress : function(current, total){
19.
console.log(current+
'/'
+total);
20.
var percent = current/total*
100
;
21.
$(
'.progressbar'
).css(
'width'
, percent+
'%'
);
22.
$(
'.progresstext .current'
).text(current);
23.
$(
'.progresstext .total'
).text(total);
24.
},
25.
onComplete : function(total){
26.
alert(
'加载完毕:'
+total+
'个资源'
);
27.
}
28.
});
29.
30.
loader.start();
各项参数都直接明了,不再多说了。在上面的例子中,我自己定义onProgress函数,做了一个简单的进度条,你也可以做其他实现。函数为你传入了current和total,分别表示当前完成的资源个数和资源总个数,可用于计算进度。
效果可看在线demo:点击这里
另外附上下载地址,感兴趣的朋友可以拿去使用:http://files.cnblogs.com/files/lvdabao/resLoader.zip
再多说两句,关于xhr2新特性
前边的废话貌似有点多。。。想直接用插件的下载下去用就好,有问题在此留言讨论。
这里想多说的东西是关于加载进度的,我上面说了我们只能获取到的是进度其实是离散的点,不是连续的。其实利用HTML5的xhr2的新特性我们也可以尝试获取更加精确的进度。因为xhr2新增了一个非常有趣的特性:可以从服务端获取文件数据。我们以前从服务端返回的数据都是字符串,现在可以直接返回Blob类型的文件。那么在这里做一个猜想,能不能利用此特性,做更加精确的进度计算呢?我在此处只是提出一种可能性,还未做实践。我们知道xhr2新增的upload属性可以让我们获取到文件上传的进度信息,但对于返回的数据,却无法直接提供进度信息,所以要想依靠它来实现还得做其他工作。
转载于:https://www.cnblogs.com/lee-my/p/loader.html
网站预加载进度条的实现相关推荐
- flex自定义preloader预加载进度条
flex默认的preloader已经很不错了,可是有时候还是需要自定义的. 需要在要出现自定义预加载的程序的<mx:Application>标签里加入preloader="&qu ...
- [html] 请实现一个网站加载进度条
[html] 请实现一个网站加载进度条 import { memo } from 'react'; import { useLifecycles } from 'react-use'; import ...
- NProgress.js - 前端全站进度条插件 - 给你的网站添加一个加载进度条
0x00 前言 前几天给博客换了@Veen Zhao大佬的Cuteen主题,非常好看,但是因为不想让自己的博客和其他人的千篇一律,于是决定在Cuteen主题的前提下逐渐设计一些自己需要的东西.正巧前几 ...
- 【原生JS插件】LoadingBar页面顶部加载进度条
先展示一下已经实现的效果: 预览地址:http://dtdxrk.github.io/js-plug/LoadingBar/index.html 看到手机上的浏览器内置了页面的加载进度条,想用在pc上 ...
- js网页顶部线性页面加载进度条,jquery头部线性进度条总结
前言 网页顶部加载进度条,近年来很流行,很多网站都采用了这种加载方式.网上也有这样类似的插件,今天我们总结一下网页顶部线性页面加载进度条. 头部LoadingBar线性进度条总结 上面的代码只是静态效 ...
- pace.js – 加载进度条插件
这儿只是简单介绍一下这个插件pace.js. 在页面中引入Pace.js,页面就会自动监测你的请求(包括Ajax请求),在事件循环滞后,会在页面记录加载的状态以及进度情况.此插件的兼容性很好,可以兼容 ...
- 一个KVO 实现WKWebView加载进度条的例子 (注意最后移除观察者)
// // OpenWebViewController.m // Treasure // // Created by 蓝蓝色信子 on 16/7/29. // Copyright © 2016年 GY ...
- WKWebView Safari调试、JS互调、加载进度条、JS中alert、confirm、prompt
主要内容 Safari调试 swift/OC与JS互调 增加加载进度条 支持JS中alert.confirm.prompt Safari调试 设置 -> safari --> 高级,开启J ...
- 小米视频加载进度条效果实现
原文:小米视频加载进度条效果实现 好吧,其实这些都是我闲暇时自己做着玩的,以前总是拿来主义,现在分享一下让我也为大家做一点贡献好了.废话不说了,看效果. 好吧 其实没什么技术含量 直接上代码好了 和我 ...
最新文章
- 关于mysql内存管理_MYSQL内存管理及优化
- ARM汇编:使用汇编语言进行数据访问时需要注意的几个问题
- JMeter打开jmx文件出错CannotResolveClassException: org.apache.jmeter.protocol.ssh.sampler.SSHCommandSampler
- lucene的丰富的各种查询
- 【混淆矩阵】matlab画混淆矩阵
- sql点滴41—MyISAM 和 InnoDB 讲解
- Go语言基础进阶—程序结构—类型
- iOS开发之获取当前手机语言
- 计算机字体颜色太浅,我的打印机打字太淡,如何调,打印的字就能够颜色
- 上海工程技术大学c语言商店存货管理系统,商店存货管理系统课程设计.doc
- Ubuntu环境下利用Stress对CPU进行满载及半载压力测试
- electron 自定义标题栏_CAXA电子图板2015版自定义标题栏
- 机器学习笔试面试整理
- Rosalind第83题:Inferring Genotype from a Pedigree
- java导出excel搜索下拉框,SXSSFWorkbook导出Excel并带下拉菜单
- python之 ffmpeg合并ts视频为mp4视频
- 学phyton第一天
- css5导弹,世界六大洲际导弹排行榜
- 使用modesim仿真的坑记录所有解决方法
- Gerber 格式详解
热门文章
- 《LeetCode力扣练习》第226题 翻转二叉树 Java
- CSP:CSP认证考试:202109-2(非零段划分)70分答案,Java版
- php sql报错1054 in,sql语句拼接 报错
- js轮询导致服务器瘫痪_演进:Tengine 从 Web 代理服务器 到 分布式推送服务器
- hive金额怎么转换千位分隔符_金额字段加千位分隔符方法
- android service是单例么,android 使用单例还是service?
- ArcGIS Server的配置
- cdh 安装_CDH 中为spark 安装 python3
- 记录一下HALCON调用相机自带驱动加速采集速率
- n1进入recovery模式_启动自动变砖模式?三星Galaxy“智能”手机