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

刘晚林 @

H5动画师

H5制作工具(http://slide.toutiao.com)

应用场景

  • 品牌:邀请函、宣传等
  • 人力:招聘
  • 广告运营:汽车、房产、美食、旅游等
  • more...

内部谁在用

  • 广告
  • 时光相册
  • 销售
  • 品牌pr
  • 内容运营
  • HR
  • 视频

特点

  1. 丰富的动画效果
  2. 关键帧设计
  3. 多种表单组件,很好地收集所需信息
  4. 免费

动画与关键帧

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

  • 群组动画
  • 叠加

谢谢

Made with Slides.com