有了 jQuery 以后,很少有人用原生js写动画效果了。
鄙人才疏学浅,闲来无事,幸甚至在,码以永志。
源码
function animate(elem, options, callback) {
if (elem == null){
console.log("animate: elem is null")
return;
}
let timer = null;
let attribute = options.attribute;
let startValue = parseFloat(window.getComputedStyle(elem)[attribute]);
if (typeof(options.value) != "string"){
throw new Error("options.value must be a string");
}
let endValue = parseFloat(options.value);
let unit = options.value.substr(endValue.toString().length);
switch (unit) {
case "px":break;
case "rem":
startValue /= parseFloat(window.getComputedStyle(document.documentElement)["font-size"]);
break;
case "em" :
startValue /= parseFloat(window.getComputedStyle(elem)["font-size"]);
break;
default :
if (!unit){
throw new Error("options.value must be a string with units, support px,rem,em");
}
throw new Error("animate can not support this unit:"+unit);
}
if (!options.intervalTime) {
options.intervalTime = 5;
}
if (startValue == endValue) {
if (callback != undefined) {
callback.call();
}
return;
}
function createTime() {
return (+new Date());
}
let startTime = createTime();
function logic() {
//开始时间 + 持续时间 - 当前时间,结果即为动画的剩余时间,当剩余时间小于0则置0,表示动画结束
let remaining = Math.max(0, startTime + options.duration - createTime());
//remaining/duration即为动画剩余的百分比,用1去减,得到已执行的百分比
let percent = 1 - (remaining / options.duration);
let nowValue = (endValue - startValue) * percent + startValue;
elem.style[attribute] = nowValue + unit;
if (percent === 1) {
clearInterval(timer);
if (callback != undefined) {
callback.call();
}
return;
}
}
timer = setInterval(logic, options.intervalTime);
}
使用方法
把animate()函数放在一个单独的 js 文件中,我把它命名为:animate.js
该函数接收3个参数:
- elm:执行动画的dom元素(必须)
- options:动画参数配置(对象,必须)
- attribute:css属性名(字符串,必须)
- value:css属性值 (字符串,必须)
- duration:动画持续时间,ms单位 (数字,必须)
- intervalTime:每一帧动画执行间隔(数字,可选)
- callback:动画执行完毕执行的回调函数(可选)
最佳实践
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>简单js动画的实现</title>
<style>
#nav {
margin-top: 20px;
width: 100px;
height: 100px;
background-color: #409eff;
position: absolute;
}
</style>
</head>
<body>
<button onclick="run()">start</button>
<div id="nav"></div>
</body>
<script src="js/animate.js"></script>
<script>
var elem = document.getElementById('nav');
//动画配置
var options = {
attribute: 'width',
value: "800px",
duration: 3000,
intervalTime : 6
};
//是否正在执行动画
let animating = false;
//点击按钮启动动画
function run() {
if (animating){
return;
}
animating = true;
animate(elem, options,function () {
animating = false;
alert("动画执行完毕");
});
}
</script>
执行效果
局限性:
只针对css属性值为Number类型的简易动画效果