@Sakura-W
2016-09-25T12:43:29.000000Z
字数 4781
阅读 1909
网络
有两种方式可以用于创建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里面有movethis.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动画的几种实现方法