动画的实现方式
实现动画的方式有以下几种:
- css3 操作简单,也最普遍常用
- JS-setInterval 定时器,每隔一定执行某种操作
- JS-setTimeout 延迟触发,每隔一定执行触发某种操作
- JS-requestAnimationFrame H5新API
实例
// Html
<div class="css3 box">css3</div>
<div id="box" class="box">setInterval</div>
<div id="box1" class="box">setTimeout</div>
<div id="box2" class="box">requestAnimationFrame</div>
// css
.css3 {
animation: move linear forwards 1670ms;
}
@keyframes move {
from {
left: 0;
}
to {
left: 500px;
}
}
.box {
position: absolute;
width: 50px;
height: 50px;
background-color: cornflowerblue;
left: 0;
}
#box {
top: 100px;
}
#box1 {
top: 200px;
}
#box2 {
top: 300px;
}
let box = document.querySelector('#box');
let box1 = document.querySelector('#box1');
let box2 = document.querySelector('#box2');
!function () {
let index = 0;
let _left = box.offsetLeft;
let timer = setInterval(function () {
if (index >= 100) {
clearInterval(timer);
} else {
index++;
box.style.left = _left + index*5 + 'px';
}
}, 16.7);
}();
!function () {
let index = 0;
let _left = box1.offsetLeft;
function move() {
index++;
box1.style.left = _left + index*5 + 'px';
if (index < 100) {
setTimeout(move, 16.7);
}
}
move();
}();
!function () {
let index = 0;
let _left = box2.offsetLeft;
function render() {
index++;
box2.style.left = _left + index*5 + 'px';
if (index < 100) {
window.requestAnimationFrame(render);
}
}
window.requestAnimationFrame(render);
}();
从运行结果来看,requestAnimationFrame是最流畅的,如果把最终left定为100px,则css3和requestAnimationFrame表现一致为最好。
抛弃
- setInterval 动画始终在抖动,失败
- setTimeout 动画会掉帧,偶尔出现跳动,失败
最终选择
- CSS3 适合简单的动画,内置曲线函数,针对opacity的动画有奇效
- requestAnimationFrame 最完美的JS动画,但是兼容性可能有问题,如果不兼容,就只能用setTimeout代替
- 第三方库 适合动画特别多且复杂的情境
requestAnimationFrame(rAF)
原理
电脑屏幕其实一直是不断变化的,它有个绘制频率,如果是60HZ,那就说明1000ms/60=16.7ms刷新一次屏幕,这个频率下人眼是识别不出来的,所以认定屏幕是不动的。那这个requestAnimationFrame,它能保证回调函数在屏幕每一次的绘制间隔中只被执行一次,这样看起来就很流畅不会丢帧
兼容
因为不同的屏幕刷新频率是不同的,而且部分浏览器并不支持这个属性,所以需要兼容
if (!Date.now)
Date.now = function() { return new Date().getTime(); };
(function() {
'use strict';
var vendors = ['webkit', 'moz'];
for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
var vp = vendors[i];
window.requestAnimationFrame = window[vp+'RequestAnimationFrame'];
window.cancelAnimationFrame = (window[vp+'CancelAnimationFrame']
|| window[vp+'CancelRequestAnimationFrame']);
}
if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) // iOS6 is buggy
|| !window.requestAnimationFrame || !window.cancelAnimationFrame) {
var lastTime = 0;
window.requestAnimationFrame = function(callback) {
var now = Date.now();
var nextTime = Math.max(lastTime + 16, now);
return setTimeout(function() { callback(lastTime = nextTime); },
nextTime - now);
};
window.cancelAnimationFrame = clearTimeout;
}
}());
cancelAnimationFrame(callback)自然就是取消动画