友情提示:如果只想实现个进度条的样式效果可以直接跳转到文章末尾的视频链接
最近客户反馈打开我们的pdf等待时间很久,要我们加个进度条告诉他们文件载入到多少了。问题来了,前端载入pdf也不知道到哪一步了,所以这个进度条完全是出于心理学上给客户一个安慰的作用,但是提出来了就得实现,先看看最终效果:
进度条
(加载出来的pdf内容经过打码处理)
首先实现样式(只提供进度条样式的实现,具体的排版根据自己的项目调整即可):
CSS:
.skill-bar {
height: 10px;
border-radius: 8px;
}
.skill-per {
height: 10px;
background-color: #0fbcf9;
border-radius: 8px;
width: 0;
position: relative;
}
HTML:
<div class="loadGifWrap">
<!--.text-center是bootstrap框架自带的class,如果不用bootstrap写styele=“text-align:center”代替即可-->
<div class="text-center loadImg_wrap">
<!--这个是示例中的小飞机的动画gif,修改为自己的动画gif文件即可-->
<img src="../static/images/load01.gif" />
<!--提示文字-->
<div class="load_text">努力加载中....</div>
<!--进度条插入位置-->
<div class="skill-bar">
<div class="skill-per" per="0"></div>
</div>
</div>
</div>
TIP:可以只把进度条.skill-bar的div插入到你需要展示进度条的位置即可。
进度条模拟思路:
样式写好了之后,就是要实现加载文件的时候进度条的动画了,下面提供我的思路,希望抛砖引玉,有更好的办法可以在评论中回复我哈!我一开始写的时候在看请求文件的接口,希望能从中获得启发,后来看到我们前端请求文件的时候是通过XMLHttpRequest实现的。XMLHttpRequest对象里面有一个属性叫readyState,当请求的时候readyState的值会不断地改变。引用一下书本中对readyState的介绍:
readyState有五种可能的值:
0 (未初始化): (XMLHttpRequest)对象已经创建,但还没有调用open()方法。
1 (载入):已经调用open() 方法,但尚未发送请求。
2 (载入完成): 请求已经发送完成。
3 (交互):可以接收到部分响应数据。
4 (完成):已经接收到了全部数据,并且连接已经关闭。
XMLHttpRequest对象可以通过onreadystatechange对readyState的值进行监听,博主在自己测试的时候发现当readyState=3的情况会多次出现,于是决定从这个入手进行模拟进度条,开始的时候进度为0,当readyState=1的时候到10%,readyState=2的时候20%,readyState=3的时候会有多次请求,因为不能预知文件的大小,我们就采取越走越慢的策略,设定几个阈值,等到达就加载的慢一些。大部分情况下文件很小,为了显示出我们进度条的存在,不管怎么样都会最后在readyState的时候强制客户看1s动画(不过分吧),所以最后取到了报告设置一个延时函数进行展示,同时将进度条相关dom元素隐藏。
JS:
$(".loadGifWrap").show();
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (req.readyState == 1) {
var $this = $(".skill-per");
var per = $this.attr('per');
$this.attr('per', "10");
$({
animatedValue: per
}).animate({
animatedValue: 10
}, {
duration: 1000,
step: function() {
$(".load_text").html(Math.floor(this.animatedValue) + "%报告请求上传中……");
$this.css("width", Math.floor(this.animatedValue) + "%");
},
complete: function() {
$this.css("width", Math.floor(this.animatedValue) + "%");
}
});
} else if (req.readyState == 2) {
var $this = $(".skill-per");
var per = $this.attr('per');
$this.attr('per', "20");
$({
animatedValue: per
}).animate({
animatedValue: 20
}, {
duration: 1000,
step: function() {
$(".load_text").html(Math.floor(this.animatedValue) + "%等待数据返回中……");
$this.css("width", Math.floor(this.animatedValue) + "%");
},
complete: function() {
$this.css("width", Math.floor(this.animatedValue) + "%");
}
});
} else if (req.readyState == 3) {
var $this = $(".skill-per");
var per = parseFloat($this.attr('per'));
var nextP;
if (per < 60) {
nextP = per + 10;
} else if (per < 80) {
nextP = per + 5;
} else if (per < 98) {
nextP = per + 0.01
} else {
nextP = 99
}
$this.attr('per', nextP);
$({
animatedValue: per
}).animate({
animatedValue: nextP
}, {
duration: 1000,
step: function() {
$(".load_text").html(Math.floor(this.animatedValue) + "%报告成功获取,努力加载中……");
$this.css("width", Math.floor(this.animatedValue) + "%");
},
complete: function() {
$this.css("width", Math.floor(this.animatedValue) + "%");
}
});
} else if (req.readyState == 4) {
var $this = $(".skill-per");
var per = $this.attr('per');
$this.attr('per', "100");
$({
animatedValue: per
}).animate({
animatedValue: 100
}, {
duration: 1000,
step: function() {
$(".load_text").html(Math.floor(this.animatedValue) + "%报告加载成功!");
$this.css("width", Math.floor(this.animatedValue) + "%");
},
complete: function() {
$this.css("width", Math.floor(this.animatedValue) + "%");
}
});
}
}
req.open("GET", url, true);
req.responseType = "blob";
req.setRequestHeader("Authorization", "Bearer " + localStorage.accessToken);
req.onload = function(event) {
if (req.status == 200) {
var blob = req.response;
var url = window.URL.createObjectURL(blob);
$("#reportWrap").attr("src", "../pdfviewer/viewer.html?file="+url); //这里用了pdf.js插件加载pdf,如果没用插件替换成原生的展示即可
setTimeout(function() {
$(".loadGifWrap").hide();
}, 1001);
} else if (req.status == 404) {
setTimeout(function() {
$(".skill-per").attr('per', "0");
$(".skill-per").css("width", 0);
$(".load_text").html("报告加载失败,尝试重新加载中!");
}, 1001);
}
};
req.send();
以上就是前端模拟进度条的实现,说实话这个功能从逻辑上来说就是伪造一个毫无意义的进度条,并没有真实的获取每一步到底到哪了,但是在心理学的角度确实会增加很多用户体验。进度条部分参考了b站搬运的一个国外的进度条视频,我这边做了些删减,如果只想要纯进度条的友友们可以直接去看我看的这个视频:
参考资料:
使用HTML CSS和JQuery的动画进度条_哔哩哔哩_bilibili
本人第二篇博客,可能讲的有点口水,希望能够帮到现在还在用jquery的你