web动画形式

经常使用的场景:

  • css3动画

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    .box {
    -webkit-transform: translate(0, 0);
    -webkit-transition: -webkit-transform 500ms;

    transform: translate(0, 0);
    transition: transform 500ms;
    }

    .box.move {
    -webkit-transform: translate(100px, 100px);
    transform: translate(100px, 100px);
    }
  • js控制样式:使用 JavaScript 来管理状态,只需在目标元素上设置相应的类,让浏览器去处理动画

    box.classList.add('move');

  • 这种方法可以侦听元素的 transitionend 事件,兼容IE10

    1
    2
    3
    4
    5
    6
    var box = document.querySelector('.box');
    box.addEventListener('transitionend', onTransitionEnd, false);

    function onTransitionEnd() {
    // Handle the transition finishing.
    }

1. CSS3动画

2. 使用 JavaScript 编写动画

为什么要使用javaScript动画,因为js动画可以完全控制元素在每个步骤的样式。这意味着您可以在您认为合适时减慢动画、暂停动画、停止动画、倒退动画和操纵元素。

1
2
3
4
5
6
7
8
var target = document.querySelector('.box');
var player = target.animate([
{transform: 'translate(0)'},
{transform: 'translate(100px, 100px)'}
], 500);
player.addEventListener('finish', function() {
target.style.transform = 'translate(100px, 100px)';
});

3. HTML5新增的定时器requestAnimationFrame

setTimeout和setInterval的问题是,它们都不精确。它们的内在运行机制决定了时间间隔参数实际上只是指定了把动画代码添加到浏览器UI线程队列中以等待执行的时间。如果队列前面已经加入了其他任务,那动画代码就要等前面的任务完成后再执行。

requestAnimationFrame采用系统时间间隔,保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,增加开销;也不会因为间隔时间太长,使用动画卡顿不流畅,让各种网页动画效果能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果.

总而言之,requestAnimationFrame相当于是把动画交给浏览器去执行,浏览器会基于当前页面情况来自行决定最佳的帧速率,从而更合理地使用CPU。

它兼容Android4.4及以上,IE10及以上,兼容性其实跟css3动画差不多,所以可能要根据需求配合setTimeout做降级处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if(!window.requestAnimationFrame){
var lastTime = 0;
window.requestAnimationFrame = function(callback){
var currTime = new Date().getTime();
var timeToCall = Math.max(0,16.7-(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);
};
}

所以综上,我们可以在使用setTimeout的地方做动画时也使用这个新的定时器做优化。

4. Web Animations API

WAAPI是JavaScript 原生提供的的动画操作 API。

文章:

CSS Animations vs Web Animations API

  • 兼容性:Dan Wilson(@danvilson) 写的WAAPI 浏览器兼容测试页面,目前只有极少部分的浏览器支持,但是 WAAPI 有完善的 Polyfill 方案。

  • WAAPI的基础方法和jQuery的.animate()方法类似

    1
    2
    var element = document.querySelector('.animate-me');
    element.animate(keyframes, 1000);

    animate 方法接受两个参数:关键帧和持续时间。与jQuery不同的是,它不仅具有浏览器原生支持等优点,而且还具有更高的性能。

    第一个参数关键帧必须是一个数组对象。每一个对象是一个动画关键帧。下面是一个简单的示例:

    1
    2
    3
    4
    var keyframes = [
    { opacity: 0 },
    { opacity: 1 }
    ];

动画与性能

High Performance Animations

  • 注意动画不能导致性能问题

    eg:

    给元素的 widthheight 设置动画会改变其几何形状,并且可能导致页面上的其他元素移动或改变大小。此过程称为布局(在 Firefox 等基于 Gecko 的浏览器中称为自动重排),如果页面有很多元素,则可能开销很大。每当触发布局时,页面或其一部分通常需要进行绘制,这一般比布局操作本身更消耗资源。

    应尽可能避免给触发布局或绘制的属性设置动画。对于大部分现代浏览器,这意味着将动画限制为 opacitytransform,两种都可经浏览器高度优化;动画是由 JavaScript 还是由 CSS 处理并不重要。

    Chrome, Firefox, Safari 和 Opera 都对 transforms 和 opacity进行硬件加速。不幸的是,对于Internet Explorer 10+ 开启硬件加速的条件不是很明确,但值得庆幸的是当F12工具加入到IE11中的时候,这一点将变得清晰。

    在Blink和WebKit内核的浏览器中,对于在CSS的transition或者animation中有opacity的改变的元素,将会为其创建一个图层。但也有很多开发者使用translateZ(0)或者translate3d(0,0,0)来人为地强制性地创建一个图层(硬件加速)。然而,需要有节制地增加图层;如果过分的增加图层,那么将会导致闪烁

    一个元素的变换,归结为改变它的位置,旋转角度和缩放。通常,位置的改变是使用lefttop属性来改变的。问题是,如前面所述,lefttop都会引起图层的变化,并且它的代价是昂贵的。更好的解决方案是使用不会引起图层变化的translate属性。

CSS 对比 JavaScript 的性能

命令式动画(JavaScript)vs说明式动画(css)

  • JavaScript动画:

    它在浏览器主进程的JavaScript中运行。主进程已经忙于运行其他的JavaScript,样式的计算,布局还有绘制。所以进程内存在这资源竞争。这实质上增加了掉帧的风险,可能这一帧是你认为最重要的帧。

  • CSS动画

    作为替代的方案,你可以用CSS来实现你的渐变和动画。最主要的好处就是,浏览器会对动画进行优化。如果有需要,它会创建图层。并且可以在主进程之外完成一些操作。这意味着,如果浏览器正在主线程上运行一些高开销任务,则这些动画可以继续运行而不中断。它最主要的缺点就是CSS动画相对于Javascript动画而言,缺乏表现力。并且很难有意义地组织动画,这意味着创造动画会带来较高的复杂度和错误率。

  • 如果任何动画触发绘制、布局或同时触发这两者,则“主线程”将必须执行工作。这点同时适用于基于 CSS 和 JavaScript 的动画,并且布局或绘制的开销可能拖慢与 CSS 或 JavaScript 执行相关的任何工作,使问题变得无意义。

总结:

JavaScript动画对比CSS动画:

缺点:

  1. JavaScript在浏览器的主线程中运行,而主线程中还有其它需要运行的JavaScript脚本、样式计算、布局、绘制任务等,对其干扰导致线程可能出现阻塞,从而造成丢帧的情况。
  2. 代码的复杂度高于CSS动画

优点:

  1. js动画控制能力强,可以完全控制元素在每个步骤的样式,如减慢动画、暂停动画、停止动画、倒退动画和操纵元素。
  2. 动画效果比css3动画丰富,有些动画效果,比如曲线运动,冲击闪烁,视差滚动效果,只有JavaScript动画才能完成
  3. JS大多时候没有兼容性问题

CSS动画对比JavaScript动画

缺点:

  1. CSS动画只能暂停,不能在动画中寻找一个特定的时间点,不能在半路反转动画,不能变换时间尺度,不能在特定的位置添加回调函数或是绑定回放事件,无进度报告
  2. 实现复杂动画代码冗长

优点:

  1. 浏览器可以对动画进行优化。

    浏览器使用与 requestAnimationFrame 类似的机制,requestAnimationFrame比起setTimeout,setInterval设置动画的优势主要是:

    1) requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。

    2) 在隐藏或不可见的元素中requestAnimationFrame不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。

  2. 强制使用硬件加速 (通过 GPU 来提高动画性能)

    渲染线程分为main thread(主线程)和compositor thread(合成器线程)。如果CSS动画只是改变transform和opacity,这时整个CSS动画得以在compositor thread完成(而JS动画则会在main thread执行,然后触发compositor进行下一步操作)在JS执行一些昂贵的任务时,main thread繁忙,CSS动画由于使用了compositor thread可以保持流畅,

  3. 代码相对简单,性能调优方向固定

在CSS动画或JS动画触发了paint或layout时,需要main thread进行Layer树的重计算,这时CSS动画或JS动画都会阻塞后续操作,所以只有用上了3D硬件加速或修改opacity时,css3动画的优势才会体现出来。

了解一个属性(由于支持度不高,暂不运用到项目):will-change:为web开发者提供了一种告知浏览器该元素会有哪些变化的方法,这样浏览器可以在元素属性真正发生变化之前提前做好对应的优化准备工作。 这种优化可以将一部分复杂的计算工作提前准备好,使页面的反应更为快速灵敏。

兼容性:IE不支持(含IE11),Android 4.4.4(含)以下不支持,ios9.2(含)以下不支持

其他参考文章:

CSS 对比 JavaScript 动画

深入理解定时器系列第二篇——被誉为神器的requestAnimationFrame