用setTimeout和setInterval来实现动画
- 没有对调用动画的循环机制进行优化
- 即使传递毫秒为单位的参数,也不能打到ms的准确性。因为JavaScript是单线程的,可能发生阻塞
- 没有考虑绘制动画的最佳时机
requestAniamationFrame
- requestAnimationFrame不需要使用者指定循环间隔时间,浏览器会基于当前页面是否可见、CPU的负荷情况等来自行决定最佳的帧速率,从而更合理地使用CPU。
- 如果想做逐帧动画,就应该用这个方法,这就要求动画函数执行会先于浏览器重绘动作。通常,被调用的频率是每秒60次。
- 回调函数只会传入一个DOMHighResTimeStamp参数,表示函数队列被触发的时间。
- requestAnimationFrame返回一个id,用于window.cancelAnimationFrame(id)来取消这个回调函数
- 兼容代码:
window.requestAnimationFrame=window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback, element) {
var start,
finish;
window.setTimeout(function () {
start = +new Date();
callback(start);
finish = +new Date();
self.timeout = 1000 / 60 - (finish - start);
}, self.timeout);
};
window.cancelNextRequestAnimationFrame = window.cancelRequestAnimationFrame
|| window.webkitCancelAnimationFrame
|| window.webkitCancelRequestAnimationFrame
|| window.mozCancelRequestAnimationFrame
|| window.oCancelRequestAnimationFrame
|| window.msCancelRequestAnimationFrame
|| clearTimeout;
requestAnimationFrame做的简易动画
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>
*{padding:0;margin: 0}
.outer{width: 100px;height: 100px;overflow:hidden;position: relative;}
.inner{
height:100px;list-style-type:none;width: 400px;
}
.inner:after{height: 0;content: '';clear: both;visibility: hidden;}
.inner li{float: left;width: 100px;height: 100px}
li:nth-child(1){background: red}
li:nth-child(2){background: black}
li:nth-child(3){background: yellow}
li:nth-child(4){background: green}
</style>
</head>
<body>
<div class="outer">
<ul class="inner">
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
<button>下一步</button>
<script type="text/javascript">
var start = null;
var element = document.querySelector('.inner')
element.style.position = 'absolute';
var cur=0,mm=100,timeid
function step(timestamp) {
if (!start) start = timestamp;
var progress = timestamp - start;
if(cur==3){
element.style.left=0;
}else{
element.style.left = -Math.min(progress / 10+cur*100, (cur+1)*100) + 'px';
}
if (progress < 1000) {
timeid=window.requestAnimationFrame(step);
}else{
cur=cur<3?cur+1:0
window.cancelAnimationFrame(timeid)
timeid=null
start=null
setTimeout(auto,1000)
}
}
var btn=document.querySelector('button')
btn.onclick=function(){
auto()
}
function auto(){
if(!timeid){
console.log(cur)
timeid=window.requestAnimationFrame(step);
}
}
</script>
</body>
</html>