H5动画师的动画设计与性能优化

刘晚林 @

H5动画师
H5制作工具(http://slide.toutiao.com)
应用场景
- 品牌:邀请函、宣传等
- 人力:招聘
- 广告运营:汽车、房产、美食、旅游等
- more...



内部谁在用
- 广告
- 时光相册
- 销售
- 品牌pr
- 内容运营
- HR
- 视频
特点
- 丰富的动画效果
- 关键帧设计
- 多种表单组件,很好地收集所需信息
- 免费

动画与关键帧

css transition

+

=

timing-function

已知起始状态和终止状态,缓动函数指定了唯一的运行轨迹

css transition的局限性
- 需要事件触发,不能自动发生
- 一次性的,除非多次触发
- 只有起始和终止状态,没有中间态
- 只能定义一个属性变化
css animation




多个状态,多个属性的变化
transform
包含多个函数translate、rotate、scale、skew、perspective、matrix

3d transform

transform: rotateY(50deg);


transform: rotateY(50deg) perspective(800px);
transform动画








如果transform的各个函数对应不上

浏览器的处理方式

矩阵反解

时刻t
计算过渡值

合成矩阵
时刻t样式:M3
动画设计
H5动画师中如何利用关键帧设计动画
设计者

数据
渲染引擎

设计器
JS动画
- 多状态控制,暂停、播放、移动到时间点、增加删除关键帧
渲染引擎
css动画
- 动画对于页面来说是只读的,不需要多状态控制;单一状态,只需要在合适的时候播放和移除动画
共同:关键帧
关键帧设计

tranform的处理
- 完全对应(如果某一帧有scalex,其他帧也有)
- 固定顺序(perspective、translate、rotate、skewx、scale)
- 只支持skewx(skewy(30deg)=skewx(-30deg)+rotatez(30deg))
优点
- transform的各个函数就成了像left、top、width一样的简单样式
- 不丢失rotate信息
关键帧编辑
0%,50%,100%
0%,50%,100%
0%,50%,100%
0%,60%,100%
删除
移动
0%{
left: 0px;
}
100%{
left: 100px;
}
left: 0
left: 100
50%
50%{
left: 50px
}
页面动画预览

- 每个元素的动画不重叠,对于某个时间点,只有一个活跃动画
- 不直接在目标元素上做动画,每个动画对于一个animator(样式计算),将活跃的animator计算的动画样式复制到目标元素
- 共用时间轴
动画渲染
数据
渲染引擎
生成keyframes和动画style
元素播放动画
交互触发动画
清除旧的动画class,添加新动画class
如果初始样式包含tranform




关键帧动画的局限性
- 关键帧与关键帧之间是单独的easing,看上去有明显的分段
- 很难实现叠加效果




动画性能优化
理想:60fps



触发layout
- layout->paint->composite
- 改变width, height, margin等和大小、位置相关的属性
- 读取size, position相关属性
clientHeight, clientLeft, clientTop, clientWidth, focus(), getBoundingClientRect(), getClientRects(), innerText, offsetHeight, offsetLeft, offsetParent, offsetTop, offsetWidth, outerText, scrollByLines(), scrollByPages(), scrollHeight, scrollIntoView(), scrollIntoViewIfNeeded(), scrollLeft, scrollTop, scrollWidth .....
触发paint
- paint->composite
- 修改border-radius, box-shadow, color等展示相关属性
composite
- GPU加速
- CPU传输到GPU的一个Bitmap
- GPU能快速对texture进行偏移、缩放、旋转、修改透明度等操作
layer

- 由于某些css样式设置,生成layer
- layer作为texture传给gpu
形成层的条件
- 3d transform
- video
- canvas
- flash
- transform、opacity动画
- filter
- 有一个z-index较低且包含一个层的兄弟节点(即该元素在层的上面渲染)

.example1 {
transform: translateZ(0);
}
.example2 {
transform: rotateZ(360deg);
}
- 过多的层占用了大量的内存
- 动画过程中几乎不会paint和layout,但是composite时间变得很长
- 动画开始卡顿
几乎每个元素都会形成层

优化层
- 移除translateZ hack
- 在进入每一页时为动画元素加上will-change(将动画元素提升为层)
- 翻页时移除上一页的动画元素的will-change
vs translatez hack
- 强制将元素提升为层的过程是很昂贵的,结果就是动画的开始时间变慢
- will-change提前通知浏览器将要发生的改变,让浏览器做好准备
- position: translate
- width/height: scale
- display/visibility: opacity


滚动


function onTouchMove (evt) {
translateY = translateY + evt.deltaY;
if (scheduledAnimationFrame)
return;
scheduledAnimationFrame = true;
requestAnimationFrame(update);
}
function update() {
container.style.transform = 'translateY(' + translateY + ') translateZ(0)';
// 其他操作
}
web animation
element.animate([
{
background: 'red',
transform: 'none',
easing: 'ease-out',
},
{
offset: 0.1,
transform: 'translateY(100px)',
easing: 'ease-in-out',
},
{
offset: 0.2,
transform: 'translate(100px, 100px)',
easing: 'ease-in-out',
},
{
offset: 0.4,
transform: 'translateX(100px)',
easing: 'ease-out',
},
{
background: 'blue',
transform: 'none',
},
], {
duration: 4000,
iterations: Infinity,
});
- 关键帧
- 动画播放控制
- Timing (easings, duration, fillMode...)
future
- 群组动画
- 叠加




谢谢
H5动画师的动画设计与性能优化
By superlin
H5动画师的动画设计与性能优化
- 214