自动化滚动实现
需求:实现一个自动化履历,页面加载,页面头部是信息栏,有状态显示和状态转动时间,出品人,开始时间,结束时间是自动化完成后显示。
下面是每一步骤的滚动,在每一步骤滚动前,需要有状态转动,有状态转动的时间,随着时间的滚动,日志显示,日志随着内容滚动,展示最新的日志,步骤完成,状态显示完成的,步骤计时器停止,步骤向上滚动一定的距离。
需求图:
思路:
一. 首先解决状态转动效果,这个可以写css,完成后覆盖即可
二. 解决每一步骤完成后向上滚动一内容的高度,同理解决日志的问题
三.解决每个步骤的计时器。
实现需求:
1.先解决状态转动的效果
这一部分就是完全是css解决,利用css动画
HTML的代码
<div class="main-load-effect"
ng-class="{successLoading:(autos.datasets.flowStatus=='Success'), failedLoading: (autos.datasets.flowStatus=='fail'),
startLoading:(autos.datasets.flowStatus == 'Running')}">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
大致的意思就是通过span变为圆形,通过改变透明度来实现转动
css的代码
//头部转圈样式
//这个是一个容器
.main-load-effect {
width:30px;
height:30px;
display: inline-block;
vertical-align: middle;
line-height: 40px;
position:relative;
}
.main-load-effect span {
display:inline-block;
width:5px;
height:5px;
border-radius:50%;
background:#48a5f4;
position:absolute;
-webkit-animation:loading 1.04s ease infinite;
}
// 通过 改变透明度实现转动效果
@-webkit-keyframes loading {
0% {
opacity:1;
}
100% {
opacity:0.2;
}
}
.main-load-effect span:nth-child(1) {
left:0px;
top:50%;
margin-top:-2.5px;
-webkit-animation-delay:0.13s;
}
.main-load-effect span:nth-child(2) {
left:3px;
top:5px;
-webkit-animation-delay:0.26s;
}
.main-load-effect span:nth-child(3) {
left:50%;
top:0px;
margin-left:-2.5px;
-webkit-animation-delay:0.39s;
}
.main-load-effect span:nth-child(4) {
top:5px;
right:3px;
-webkit-animation-delay:0.52s;
}
.main-load-effect span:nth-child(5) {
right:0px;
top:50%;
margin-top:-2.5px;
-webkit-animation-delay:0.65s;
}
.main-load-effect span:nth-child(6) {
right:3px;
bottom:5px;
-webkit-animation-delay:0.78s;
}
.main-load-effect span:nth-child(7) {
bottom:0px;
left:50%;
margin-left:-2.5px;
-webkit-animation-delay:0.91s;
}
.main-load-effect span:nth-child(8) {
bottom:5px;
left:3px;
-webkit-animation-delay:1.04s;
}
//头部转动结束
//最终样式
.successLoading {
width:25px;
height: 25px;
background: green;
border-radius: 50%;
span{
display: none;
}
}
.failedLoading {
width:25px;
height: 25px;
background: red;
border-radius: 50%;
span{
display: none;
}
}
实际的效果如下图所示:
- 完成滚动条
完成滚动是需要滚动条滚动,js有滚动条事件,scroll()事件
$(selector).scroll(function) 是scrolld的语法,function是触发的函数当滚动条滚动触发的函数,
如:
$("div").scroll(
function(){
console.log(" 我滚啦");
}
)
当滚动条滚动就会打印出:“我滚啦”
也可以设置滚动条的初始高度 scrollTop
Element.scrollTop 属性可以获取或设置一个元素的内容垂直滚动的像素数。一个元素的 scrollTop 是可以去计算出这个元素最高高度距离它容器顶部的可见高度。当一个元素的容器没有产生垂直方向的滚动条,那它的 scrollTop 的值默认为0.
也就是说需要一个容器,需要给容器设置一个高度,只有内容过多,超过容器的高度才会出现滚动条,
<div class="logAutoScroll" style="width:100%; height:80%;overflow-y: auto;" >
<div class="logAutoContent">
{{item.stepLog}}
</div>
</div>
这是个日志,会随着stepLog的内容,填充容器,如果需要设置日志始终随着日志的滚动而滚动,只需要设置
var oLog =document.getElementsByClassName("logAutoScroll")[i];
var oLogContent =document.getElementsByClassName("logAutoContent")[i];
$(oLog).scrollTop(oLogContent.scrollHeight);
Element.scrollHeight 是计量元素内容高度的只读属性,包括overflow样式属性导致的视图中不可见内容。没有垂直滚动条的情况下,scrollHeight值与元素视图填充所有内容所需要的最小值clientHeight相同。包括元素的padding,但不包括元素的margin.
这样就可以一直设置为滚动条随着内容滚动
判定元素是否滚动到底
如果元素滚动到底,下面等式返回true,没有则返回false.
element.scrollHeight - element.scrollTop === element.clientHeight
- 解决每个步骤的计时器
a.这个比较麻烦,因为工程使用的是angular,每一个步骤使用的是ng-repeat,也就是一个变量使用,如果改变一个变量,这样所有的步骤都会改变,这就需要给每一个步骤重新赋值一个变量,刚开始是这样想的,但是楼主技术不行,不会给每个步骤赋值一个新的不同的变量,请教一个大神才知道。
可以写一个方法,把每个步骤的序号或者$index传进去,然后返回一个变量。这个变量也是动态生成的。
动态生成变量:
self.datasets.steps.length这个是需要多少变量的长度
//生成动态变量
for(var j=0;j<self.datasets.steps.length;j++){
self["step"+(j+1)] = 0;
}
ng-repeat 中的变量是这样的 {{autos.getStepNum($index)}}
这样就是把$index 传进去的,在getStepNum()这个方法中这样写
//根据stepsIndex动态返回相应的变量
self.getStepNum = function (row) {
console.log("row",row);
switch(row) {
case row:
return self["step"+row];
}
};
这样就会得到几个不同的变量,分别是
self.step0
self.step1
self.step2
self.step3
self.step4
每个步骤的计时器只需要赋给对应的变量就行了,不会相互影响
计时器的计算,无非就是使用 setInterval使的一个变量一直增加
setInterval 有几种写法,我感觉是比较迷惑人的,一种是在内部直接写的
var time = setInterval(function(){
self["step"]++;
$scope.$evalAsync();
},1000);
另一种是需要写成函数的形式
var time = setInterval(data,1000);
function data(){
self["step"]++;
$scope.$evalAsync();
}
没有哪个是最好的,看个人喜好就可,上面的代码也正是定时器的写法,只不过写的简单些,每个步骤并未赋值一个刚才创建的变量。
化秒为分和小时
//self["timer"+(i+1)] 就是得到的秒数
var theSecond=parseInt(self["timer"+(i+1)]);
var theMinute=0;
var theHour=0;
if(theSecond>60){
theMinute=parseInt(theSecond/60);
theSecond=parseInt(theSecond%60);
if(theMinute>60){
theHour=parseInt(theMinute/60);
theMinute = parseInt(theMinute%60);
}
}
self["step"+(i+1)]=""+parseInt(theSecond);
$scope.$evalAsync();
if(theMinute>0){
self["step"+(i+1)]=""+parseInt(theMinute)+"分"+self["step"+(i+1)];
$scope.$evalAsync();
}
if(theHour>0){
self["step"+(i+1)]=""+parseInt(theHour)+"小时"+self["step"+(i+1)];
$scope.$evalAsync();
}
在这里面也有一段逻辑要思考,就是如何判断每个步骤正在跑或者已经完成,这就需要循环每个步骤的状态了,如果显示一个步骤正在跑,那么就启动计时器,日志开始滚动,如果每个步骤已经完成,就清除定时器,然后向上滚动一段距离,当所有的步骤都已经完成,再清除主定时器,或者失败也要清除主定时器,这段代码较长,在此不做粘贴,所有的代码已经上传到codepen