创新高性能移动 UI 框架-Canvas UI 框架

最近有人在知乎讨论 react native,我也凑个热闹,来个技术贴。
webview 里无法获得的能力虽然是「体验增强」与「端基本能力」,但现都基本上有成熟解决方法。但后期的 ui 和 layout 的性能反而是目前 web 技术欠缺的。所以,无论是 titanium 与 react native 都是解决性能作为探索的出发点。
性能慢与快的分水岭
慢与快的标准,是按照每秒大于等于 60 fps(60 帧每秒) 的理论,而为什么是 60 fps,这不多描述。
按此理论,那么「每帧」里所有的操作都必须在 16ms 完成。
webview 里 ui 性能慢的原因webview 单线程模型;dom/css 排版复杂,渲染上需要大量计算;动画是也很重要的考量因素。多说两句动画。
最早做动画都是用 settimeout/setinterval。而 settimeout/setinterval 的处理回调的时间 tick time 精度都在 16ms 左右。
所以,可以想象正常用这两个函数就已经 16 ms了,再加 reflow/repaint/compositing 卡顿或跳帧就是家常便饭了。
还好的是 w3c 标准和各浏览器厂商较早就支持了动画接口 raf(requestanimationframe 函数)来处理动画帧回调。解决了上述 settimeout/setinterval animation 不足的问题。
dom 性能低下的原因
浏览器执行的几个步骤:
restyle/reflow/repaint 触发条件:
了解完以上信息,考虑以下条件:
把 javascript 逻辑、复杂的 dom 与样式合成,并完成渲染;http 请求下载多媒体;在一个线程里;移动上的 arm 架构;以上操作能在每帧 16ms 里完成,想想都觉得是一件 tmd「不可思议」的事情。于是各种各样的奇葩优化出现了。
webview 里高性能组件分类已知的高性能组件的几类方法:
常规方法:这类的原理主要是利用人为或规范的方式,减少 restyle/reflow/repaint 触发次数:
通用组件优化 dom 结构,甚至用 virtual dom(虚拟 dom)减少 reflow 和 dom 的复杂度;优化 css,少用或跳过 repaint 阶段。用编译的手段识别部分 css,将 left/top 变换变成 transform;
跳过 layout 与 paint 阶段,就是多使用 layer composite 技术,即 css 的「opacity」和「transform」属性作动画。
只能在 css 和 dom 结构上去抠出些性能优化的空间,缺陷优化空间有限;这种优化技巧通常是放在最后调优时冲剌使用,不能做为常规手段。
进阶方法原理是尽可能利用 native 能力,甚至将 javascript 转换成 native app 代码。
用 javascript 调起 native 组件,将增强与高性能组件交给 native 来处理,以前在 fex 提的「轻组件」就是这么做的。这个原理类似 pc 时代的 activex;将 webview 里无法实现的功能用 native 实现。利用 native activity 的渲染线程,分担浏览器渲染压力(webviewcorethread 是 webview 线程)。最 dirty 的事在于处理 native 上 ui 的层次管理。需要后台有线程一直在检测 scroll/resize/ui change 时 ui 边界是否有相互覆盖与叠加的问题。javascript 翻译成 java/oc 代码。类似 react native/titanium,将 javascript 翻译成 native 代码,特别是 ui 组件上。(有兴趣的同学可以反编译 react native 写的 facebook group)例:用 react,通过虚拟 web ui 映射至 native view,并且将代码逻辑翻译成 native。新方法 — canvas ui这也是要说的重点,用「开发游戏」的思路来做 ui 组件探索,我把它称为 canvas ui framework。
canvas ui framework用游戏的思路做 ui,最早我有这个想法是 2014 年。
为什么要用 canvas?canvas 是 h5 的画布元素,即一个 dom 元素。通过脚本控制逻辑给画布上增加文字与图像,而浏览器只需要绘制一次形成一幅图。
只用一个 canvas dom 元素,降低 dom 数量与渲染的复杂度,可以将原来 cpu 密集型变成 gpu 操作。绝大多数针对 canvas 是用硬件 gpu 加速渲染。gpu 的 alu(计算单元) 比 cpu 要多很多,而控制运算(逻辑)则可以用 javascript 在 cpu 里做,甚至还可以用 webworker 多线程处理 cpu 密集型的操作,从而达到充分利用硬件资源的能力。canvas 画布无论是 javascript & h5,还是 native 都有类似的 api。所以:本地调试可在浏览器里完成。最差方案可以用 canvas ui 跑在浏览器里。更进一步,可以把浏览器 canvas 接口的反射到用 native 画布上,以此提高性能。值得一提的是,腾迅的 x5 内核已经将 egret(白鹭游戏引擎与cocos2dx)内置,所以时间线拉长来看,webview 的画布功能将会更加强大。
在 2014 年中时,很多人见识过默认置入 cocos2dx 引擎的浏览器,用 webview 玩「捕鱼达人」很流畅。
由此说明 canvas 做 ui 组件可行性还是蛮高的。
解决方案用游戏的思路来解决 dom paint 的问题,业界早就有实验。最早实验的是 zynga 做 angry birds 游戏的厂家,2010 年写的 demo scroller:
https://github.com/zynga/scroller
设计、开发一个基于 canvas 的 ui 框架系统,由于系统相对比较复杂,需接管浏览器构建的整个过程:
验证在实践环境中的效果,要把原来页面的 dom 写成 canvas,再加上一些调优与比较,工作量相对大,(包括 zynga 也只是实现了一个简单的 demo 而已)
就暂时搁置了。
最近这阵子在翻 github 与新闻时,我惊喜的发现也有人在做同样的事了,最后发现 flipboard 同学们写的一个 demo:
https://flipboard.com/@flipboard/flipboard-picks-8a1uu7ngz
这个 demo 足够复杂,动画也足够多、炫。是用 canvas 来构建整个 ui。
测试过后:
这么复杂的 demo 在 mi4 以及配置以上性能很好,流畅度无限接近于 native,比较理想。对比过 g+ 的 android 应用,g+ 的 app 从动画上比 flipboard 提供的的 demo 还「卡」些。在小米 note 上的动画流畅度已秒掉 iphone 6,非常赞。按照摩尔定律,可以预计明年 note 的标配的 cpu 和 gpu 配置会成为主流。
而现在用 canvas ui 框架用在 mi4 以下机器仍然比较慢。而 2015 年 h5 开发 app,对很多公司来说只是 plan b 计划,大公司甚至 plan b 都不是。所以,如果一定要在纯 h5 上搞牛逼动画,还是再等等吧。
布局系统 css layout说回到 canvas component framework,回到我上面画的这张图:
ui 组件基于「文本」与「图像」。但 framework,除了 ui 组件本身以外,还需要有 layout,而 css 只适用于浏览器本身的 layout 而无法适用于 canvas 画布。
要给开发者好且排版可控的方案,那就要开发一个用 javascript 实现类似 css 的布局子集的框架。
否则 ui 的组件在画布上没有 layout 就无意义。
这个布局框架实现成本(简单实现)理论上并不大,大的是在于未来增加新 feature 并相互组合时与浏览器本身有差异,需要有完整的 unit test。正好最近 facebook 也开源了一个用 javascript 写 css layout 子集的解决方案,实现了:
paddingwidthmarginborderflexposition( relative/absolute )等等 feature。
github 地址:https://github.com/facebook/css-layout
这些 css 布局子集基本能满足我们前期开发预期。
开发框架用 css-layout 再加上 ui 管理层,就可以比较清晰的实现出 canvas 的 ui 组件框架了。那么,剩下的事就是:
应用开发框架的选择,如:选择 react/mvc 框架。模拟 dom 层次,即图层管理。并且,让我非常欣喜的是,flipboard 在 2 月已经完成了构建,基于 react 框架。 https://github.com/flipboard/react-canv
上一个:济南英文网站建设注意事项?哪家好?
下一个:重要的设计方法论整理
石家庄网站建设,石家庄做网站,石家庄网站设计