TAT.dnt Omi 拥抱 60FPS 的 Web 动画
In 未分类 on 2018年11月07日 by view: 6,290
0

写在前面

Omi 框架 正式发布了 → omi-transform

Made css3 transform super easy. Made 60 FPS easy.

作为 Omi 组件化开发特效运动解决方案,让你轻松在 Omi 项目里快速简便支持 CSS3 Transform 设置。css3transform 是经受过海量项目洗礼的,作为移动 Web 特效解决方案,在微信、手 Q 兴趣部落、日迹、QQ 群、QQ 附近等项目中广泛使用,以激进的修改 DOM 属性为代价,带来极为便利的可编程性。

你可以通过 css3transform 官方首页快速了解它。

上面官网的例子都是原生 js 的,css3transform 也拥有 react 版本,你也可以在 react 中以声明式的方式使用 css3transform:

这都不是重点,重点是 omi-transform。

3 分钟掌握 omi-transform

通过 npm 安装

使用

  • 把需要运动的 DOM 使用 <css3-transform></css3-transform> 包裹
  • 在需要使用 css3transform 的 DOM 上标记 ref 用来直接操作 DOM
  • 在组件函数里便可以使用 this.refs.animDiv 来读取或者设置 css transform 属性
  • this.refs.xxx 支持 "translateX", "translateY", "translateZ", "scaleX", "scaleY", "scaleZ", "rotateX", "rotateY", "rotateZ", "skewX", "skewY", "originX", "originY", "originZ", "perspective" 这些属性设置和读取
  • perspective 表示透视投影的距离

组件里的某个 DOM 在运动过程中,可能会由于其他逻辑,进行 update。有可能是用户交互,有可能是数据返回的回调。所以,update 前后,DOM 的状态的保留显得尤其重要,不然的话就会有闪烁、跳跃的效果或者其他显示逻辑错误。

可以看到上面的代码在 DOM 运动过程中时不进行 Diff ?组件不进行 update ?万一组件 update,所有运动的状态都会丢失?Omi 怎么解决这个问题?上面的代码已经给出了答案:

使用 this.data.rotateZ 来同步运动 DOM 的状态防止意外的刷新 (update)

→ 演示

支持的属性

Property Describe
translateX translateX
translateY translateY
translateZ translateZ
scaleX scaleX
scaleY scaleY
scaleZ scaleZ
rotateX rotateX
rotateY rotateY
rotateZ rotateZ
skewX skewX
skewY skewY
originX the basic x point of rotation
originY the basic y point of rotation
originZ the basic z point of rotation
perspective Perspective projection distance

你既可以 get 也可以 set。

性能对比

因为 react 版本会有 diff 过程,然后 apply diff to dom 的过程,state 改变不会整个 innerHTML 全部替换,所以对浏览器渲染来说还是很便宜,但是在 js 里 diff 的过程的耗时还是需要去 profiles 一把,如果耗时严重,不在 webworker 里跑还是会卡住 UI 线程导致卡顿,动画卡顿丢帧、交互延缓等。所以要看一看 CPU 的耗时还是很有必要的。

下面数据是对比 omi-transform 和 react-transform,两种方式使用 chrome profiles 了一把。

先看总耗时对比

react-transform:

omi-transform:

  • react 在 8739 秒内 CPU 耗时花费了近似 1686ms
  • Omi 方式在 9254ms 秒内 CPU 耗时花费近似 700ms

在不进行 profiles 就能想象到 react 是一定会更慢一些,因为 state 的改变要走把 react 生命周期走一遍,但是可以看到 react 的耗时还是在可以接受的范围,没有慢到难以接受。

而 Omi 的方式则和传统的原生 js 的耗时一模一样。因为运动过程不进行 DOM Diff,直接操作 DOM!!

Omi 自身对比

主要对比上面两个代码块的执行效率,打开谷歌浏览器的 Performance 运行 10 秒左右,打开 Summary 对比:

Slow Fast
Omi Omi

可以看到 omi 的两种方式都拥有很高性能,10 秒钟内拥有大量的空闲时间,但是 fast 确实更加 fast,scripting 的耗时更短。但是优势不明显是为什么?因为 DOM 结构简单,如果 DOM 结构越复杂, fast 直接操作 DOM 的方式会把 slow 的方式甩开一大截!下面进行验证一下:

先发 render 的 DOM 结构修改成复杂的: