分享一个用原生JS实现的定时器多段动画,效果如下:
代码实现如下,详情请看代码注释:
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>原生JS实现定时器多段动画</title>
<style>
* {
margin: 0;
padding: 0;
}
#btn1 {
position: relative;
left: 50%;
top: 300px;
transform: translate(-50%, -50%);
}
#box {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
left: 50%;
top: 50%;
margin-left: -50px;
margin-top: -50px;
}
</style>
</head>
<body>
<button id="btn1">运动</button>
<div id="box"></div>
<script>
var btn1 = document.getElementById("btn1");
var box = document.getElementById("box");
var timer = null;
btn1.onclick = function () {
// 我们想要通过多次调用animate,实现多段运动
// 但是只会执行后一个,原因是后面的调用将前面的调用定时器清除
// 我们需要的是当第一次运动完成后,再去执行第二个运动
// 代码修改后
animate(box, {
width: 200,
height: 170,
left: 130,
top: 240,
opacity: 0.5,
zIndex: 3
}, function () {
animate(box, {
width: 300,
height: 270,
left: 230,
top: 140,
opacity: 0.7,
zIndex: 1
});
});
};
animate(box, {
width: 100,
height: 200
}, function () { });
// 可以让多个样式同时进行运动的animate
function animate(tag, obj, fn) {
// 停止加速
clearInterval(tag.timer);
tag.timer = setInterval(function () {
// 假设本次可以进行清除
var flag = true;
for (var k in obj) {
// 针对opacity和zIndex进行单独处理
if (k == "opacity") {
var target = obj[k] * 100;
var leader = getStyle(tag, k) * 100 || 0;
var step = (target - leader) / 10;
// 设置取整,保证元素可以进行运动
step = step > 0 ? Math.ceil(step) : Math.floor(step);
leader = leader step;
// 缩小对应的倍数,并且去除单位
tag.style[k] = leader / 100;
} else if (k == "zIndex") {
// zIndex不需要运动,只要进行修改设置即可
tag.style.zIndex = obj[k];
} else {
// k - 属性名 - attr - 要修改的样式名
// obj[k] - 属性值 - target - 要修改的样式的目标值
var target = obj[k];
var leader = parseInt(getStyle(tag, k)) || 0;
var step = (target - leader) / 10;
// 设置取整,保证元素可以进行运动
step = step > 0 ? Math.ceil(step) : Math.floor(step);
leader = leader step;
tag.style[k] = leader "px";
}
// 如果有某一个样式没有运动到指定位置,阻止清除
if (leader != target) {
flag = false;
}
};
if (flag) {
clearInterval(tag.timer);
fn && fn();
}
}, 20);
};
// 由于获取标签任意样式的值
function getStyle(tag, attr) {
if (tag.currentStyle) {
return tag.currentStyle[attr];
} else {
return getComputedStyle(tag, null)[attr];
}
}
</script>
</body>
</html>