@Sakura-W
2016-09-25T12:43:29.000000Z
字数 4781
阅读 1801
网络
有两种方式可以用于创建Web动画:CSS和JavaScript。选择哪一种方式取决于项目的其他依赖以及想要达到的效果。
选择原则如下:
1)当UI元素发生较小的独立状态改变时,使用CSS。比如导航菜单或者文字提示等。虽然最终可以使用JavaScript来控制状态切换,但动画本身采用CSS。
2)当需要对动画进行大量的控制的时候,使用JavaScript。动态跟踪触摸位置的动画或需要停止、暂停、减速或倒退的动画一般需要使用JavaScript。
3)当要重新手动绘制整个画面的时候,采用requestAnimationFrame。比如创建一个游戏或者HTML canvas应用
HTML:
<div class="box"></div>
CSS:
.box{
width: 200px;
height: 200px;
margin-left: 20px;
margin-top: 20px;
box-shadow: 0px 0px 5px #444;
transform: translate(0,0);
transition: transform .5s;
-webkit-transform: translate(0,0);
-webkit-transition: transform .5s;
}
.box.move{
transform: translate(200px,200px);
-webkit-transform: translate(200px,200px);
}
JavaScript:
(function(){
var box = document.querySelector(".box");
box.addEventListener("click", function(){
if(this.classList.value.indexOf("move") != -1){//表示classList里面有move
this.classList.remove("move");
}else{
this.classList.add("move");
}
}, false);
}());
所以,常见的用法就是用JavaScript来控制状态,即为动画元素添加类名,用CSS来实现动画。也可以监听transitionend事件(transition结束事件),但IE,只有IE10及以上版本才支持,其他浏览器都在某些版本支持:
box.addEventListener("transitionend", function(){
if(this.style.backgroundColor === ""){
this.style.backgroundColor = "red";
}else{
this.style.backgroundColor = "";
}
}, false);
以上代码在动画结束后改变box盒子的颜色。
HTML:
<div class="box"></div>
CSS:
.box{
width: 200px;
height: 200px;
margin-left: 20px;
margin-top: 20px;
box-shadow: 0px 0px 5px #444;
animation-name: movingBox;
animation-duration: 1s;
animation-fill-mode: farwards;
animation-iteration-count: infinite;;
}
@keyframes movingBox {
0%{
transform: translate(0,0);
}
25%{
transform: translate(100px,0);
}
50%{
transform: translate(100px,100px);
}
75%{
transform: translate(0,100px);
}
100%{
transform: translate(0,0);
}
}
利用animation属性可以在不用JavaScript的情况下实现动画的各种状态的切换。
HTML:
<div class="box"></div>
JavaScript:
(function(){
var box = document.querySelector(".box");
var player = box.animate([
{transform: "translate(0)"},
{transform: "translate(100px, 100px)"}
], 500);
player.addEventListener("finish", function(){
box.style.transform = "translate(100px, 100px)";
});
}());
目前Chrome和Opera已经支持动画API,Firefox正在开发,对于其他浏览器则可以采用兼容工具:web-animations.
Web动画API参考:Web Animations
我们通常使用定时器来循环改变目标物体的状态,从而实现动画。一般而言,用setTimeout
做动画比setInterval
性能更高:
HTML:
<div class="box"></div>
CSS:
.box{
position: absolute;//要求绝对定位
left: 0;
top: 0;
width: 200px;
height: 200px;
box-shadow: 0px 0px 5px #444;
}
JavaScript:
(function(){
var box = document.querySelector(".box");
function move(){
box.style.left = box.offsetLeft + 5 + "px";
if(box.offsetLeft <= 300){
setTimeout(move, 30);
}
}
setTimeout(move, 0);
}());
用以上方式模拟setInterval,性能更高!!
语法:requestAnimationFrame()
函数与setTimeout
类似,该函数接收一个函数作为参数,该函数通常会在1秒内调用60次,这样动画呈现更加流畅。该函数接收一个参数,表示当前时间,即调用该函数的时间点。
var animate = window.requestAnimationFrame(callback);
该函数返回一个长整型数值,便于取消动画(类似定时器):
window.cancelAnimationFrame(animate);
例子:
(function(){
var box = document.querySelector(".box");//该元素也需要绝对定位
var start = null;
function step(timestamp){
if(!start){
start = timestamp;
}
console.log(start);
console.log(timestamp);
var progress = timestamp - start;
box.style.left = Math.min(progress/10, 200) + "px";
if(progress < 2000){//终止条件是box.offsetLeft < 200,这样就不用实时检测了
window.requestAnimationFrame(step);
}
}
window.requestAnimationFrame(step);
}());
简单兼容写法:
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
}());
Paul Irish及其他贡献者放在GitHub Gist上的代码片段,用于在浏览器不支持requestAnimationFrame情况下的回退:
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
// MIT license
(function() {
var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame) window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() {
callback(currTime + timeToCall);
}, timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}());
requestAnimationFrame()
函数是针对动画效果的API。采用这个API,浏览器可以优化并行的动画动作,更合理的重新排列动作序列,并把能够合并动作放在一个渲染周期内完成,从而呈现更流畅的动画效果。通过requestAnimationFrame()
,JS动画能够和CSS动画或SVG SMIL动画同步发生。另外,如果在一个浏览器标签页内运行一个动画,当这个标签不可见时,浏览器会暂停它,节省资源。
参考:
CSS vs JavaScript animations
window.requestAnimationFrame()
Web动画的几种实现方法