canvas教程

Canvas UI 高性能的移动 UI 框架

字号+ 作者:H5之家 来源:H5之家 2017-07-17 12:01 我要评论( )

性能慢与快的分水岭. 慢与快的标准,是按照每秒大于等于 60 FPS(60 帧每秒) 的理论,而为什么是 60 FPS,这不多描述。 按此理论,那么「每

性能慢与快的分水岭.

慢与快的标准,是按照每秒大于等于 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 里高性能组件分类.

已知的高性能组件的几类方法:

1)常规方法

这类的原理主要是利用人为或规范的方式,减少 restyle/reflow/repaint 触发次数:

* 通用组件优化 DOM 结构,甚至用 Virtual DOM(虚拟 DOM)减少 reflow 和 DOM 的复杂度;
* 优化 CSS,少用或跳过 repaint 阶段。用编译的手段识别部分 CSS,将 left/top 变换变成 transform;

跳过 layout 与 paint 阶段,就是多使用 Layer composite 技术,即 css 的「opacity」和「transform」属性作动画。

只能在 css 和 DOM 结构上去抠出些性能优化的空间,缺陷优化空间有限;这种优化技巧通常是放在最后调优时冲剌使用,不能做为常规手段。

2)进阶方法

原理是尽可能利用 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。

3)新方法 — 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。

测试过后:

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • js应用:使用canvas给图片加水印

    js应用:使用canvas给图片加水印

    2017-07-16 18:01

  • 第十二讲:canvas实例3-在线画图工具-画线和属性设定.zip

    第十二讲:canvas实例3-在线画图工具-画线和属性设定.zip

    2017-07-16 18:00

  • JSP_strut2架构下前台使用canvas对接收到的后台数据画图的一种

    JSP_strut2架构下前台使用canvas对接收到的后台数据画图的一种

    2017-07-16 17:15

  • JavaScript html5 canvas绘制时钟效果

    JavaScript html5 canvas绘制时钟效果

    2017-07-16 16:03

网友点评
c