21.优化 CSS 动画性能
Opened this issue · 0 comments
ccforward commented
极可能的加速 CSS 动画性能
最近在研究 web 性能优化的问题,看了来自Google的文章《FLIP your animations》
这篇文章提供了一种优化动画性能的方法,但是实现起来略微复杂,不过前端界本来就是各种 Hack 大行其道,所以简单了解了下其原理:
通过在100ms的动画响应延迟窗口期内计算动画初始与终止的属性差值,把动画尽量转换为只变化transform或opacity这类只触发重组不会触发重绘与重排的属性。
100ms
关于什么是动画响应的延迟时间,为什么会是100ms?100ms可以说是人类大脑的时间常量值,如果一个动作在触发后立即执行,视觉上就会有一种违和的感觉,而延迟100ms才响应的体验是让人感到最舒服的,关于100ms延迟具体细节可以查看人机交互领域大师的这几篇文章:
- Card, S. K., Robertson, G. G., and Mackinlay, J. D. (1991). The information visualizer: An information workspace. Proc. ACM CHI'91 Conf. (New Orleans, LA, 28 April-2 May), 181-188.
- Miller, R. B. (1968). Response time in man-computer conversational transactions. Proc. AFIPS Fall Joint Computer Conference Vol. 33, 267-277.
- Myers, B. A. (1985). The importance of percent-done progress indicators for computer-human interfaces. Proc. ACM CHI'85 Conf. (San Francisco, CA, 14-18 April), 11-17.
PS: 上面文章之前同事有推荐过,但是具体内容我没有细看。
动画实现
整个动画过程的实现代码大概如下:
// 1. 获取开始位置的状态
var first = el.getBoundingClientRect();
// 2. 通过添加样式类设置元素为最终位置的状态
el.classList.add('at-the-end');
// 3. 获取最终位置的状态
var last = el.getBoundingClientRect();
// 4. 计算初始与终止位置状态的差值,这里只计算top属性为例,通常需计算以下属性差值:left、top、width、height、scaleX、scaleY、opactiy
var difference = first.top - last.top;
// 5. 通过transform设置位置偏移
el.style.transform = 'translateY(' + difference + 'px)';
// 6. 等待下一帧生效,确保第5步已经生效
requestAnimationFrame(function() {
// 7. 添加样式类,让动画跑起来
el.classList.add('animatable');
// 8. 重置transform
el.style.transform = '';
});
// 9. 动画结束后移除添加的类
el.addEventListener('transitionend', function transitionend() {
el.classList.remove('animatable');
el.removeEventListener('transitionend', transitionend)
});
关于 requestAnimationFrame 的使用,写了一段兼容代码:
requestAnimationFrame.js
其中 animatable
样式规则如下,transition-property
设置为 tranform
与 opacity
, transition-duration
与 transition-timing-function
可按需求自定义设置:
.animatable {
transition: transform 1s linear, opacity 1s linear;
}
我个人认为,无论何时,性能优化总是不能达到极限,所以性能优化要一直持续下去。