GCanvas 渲染引擎介绍
GCanvas 已经正式开源,开源官方主页,传送门
GCanvas 提供了一套类似于 H5 Canvas 标准的 JavaScript API。基于这套 API 可以方便的去做图形绘制、动画渲染等,开发的体验与 H5 Canvas 是完全一样的。
GCanvas 介绍
GCanvas发展经历了两个阶段。
第一阶段,2014 年中到 2015 年底,解决 Android 平台 WebView Canvas 渲染性能差的问题。 第二阶段,2016 年 11 月到现在,为前端提供 Native 图形绘制能力。用一句话来概括 GCanvas,即遵循 W3C 标准,移动端的跨平台的高性能图形渲染引擎。可以从三个方面来解释。
遵循 W3C 标准
GCanvas 提供了一套类似于 H5 Canvas 标准的 JavaScript API,开发人员基于这套 API 可以方便的去做图形绘制、动画渲染等。开发的体验与 H5 Canvas 是完全一样的。
跨平台
GCanvas 的内核基于 OpenGL ES, 用 C++ 实现了一套用于描述 Canvas 标准 API 的接口实现。我们将其称为渲染引擎内核。并通过交叉编译,使得可以适配 Android、iOS 这两大主流移动平台,因而具有跨平台的特性。
高性能
早期移动平台上 H5 Canvas 去做一些复杂的动画或游戏,在 WebView 上的体验非常差。 主要原因是 WebView 对 GPU 硬件加速的支持差。高性能则是充分利用了 GPU 硬件的渲染能力,主要体现两个方面:
GCanvas 组成
如上图所示 GCanvas 由三层组成 JavaScript 层、插件层、核心渲染库。
JavaScript 层
JavaScript 提供对外统一的 API,支持 Canvas 2D 和 WebGL 的功能接口。接口支持情况请参考 API 覆盖。
插件层
插件层核心包含三部分。
Bridge 桥接
JavaScript 到 Native 的桥接,比较主流的方式 JSBridge 和 JSBinding。JSBridge 实现方式,如 Cordva、WebviewJavascriptBridge 等。 还可以用 JSBinding 方式来实现,如 V8、JavascriptCore 等。实际的应用场景中这两种桥接方式都有支持。
通用插件
通用插件包含了通用插件接口与实现、GCanvas 的管理、渲染命令队列管理、纹理缓存等。支持不同类型桥接方式下的扩展。
系统适配
系统适配涉及 Android 和 iOS 对 OpenGL ES 实现的差异,网络图片下载,字体渲染等方面。
核心渲染库
核心渲染库包括对外统一的接口,以及 Contex2D 和 WebGL 模块,底层则是对 OpenGL ES API 等分装。
GCanvas 流程
上图是 JavaScript 层渲染核心库的概要流程,关键的两个流程是初始化和渲染。
初始化
初始化,JavaSript 层获取配置判断运行环境,通过桥接层,插件层完成视图和 GCanvas 的创建。进一步完成对 OpenGL 环境的初始化。
渲染
渲染,JavaScript 层将所有的API调用托管,并且转换成自定义的命令格式(命令类型 + 参数的组合)。渲染触发则由 JavaScript 定时器触发或者手动触发的方式,将这些命令下发到渲染核心库执行。
以 Weex 为例, 绘制图形和图片的测试代码如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<template>
<div>
<gcanvas v-if="isWeex" ref="canvas_holder" style="top: 0; width:750;height:1000;position:absolute;"></gcanvas>
<canvas v-if="!isWeex" ref="canvas_holder" style="width:750px;height:1000px;"></canvas>
</div>
</template>
<script>
const isWeex = weex.config.env.platform !== 'Web'
const { enable, WeexBridge, Image: GImage } = require('gcanvas.js');
const EnvImage = !isWeex ? Image : GImage;
export default {
data() {
return {
isWeex: isWeex ? 1 : 0
}
},
mounted: function () {
let ref = this.$refs.canvas_holder;
if (isWeex) {
ref = enable(ref, {bridge: WeexBridge});
}
var ctx = ref.getContext('2d');
//rect
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 100, 100);
//rect
ctx.fillStyle = 'black';
ctx.fillRect(100, 100, 100, 100);
ctx.fillRect(25, 210, 700, 5);
//circle
ctx.arc(450, 200, 100, 0, Math.PI * 2, true);
ctx.fill();
//drawImage
var image = new EnvImage();
image.onload = function(){
ctx.drawImage(image, 100, 330);
ctx.drawImage(image, 100+300, 330, 225, 75);
}
image.src = 'https://gw.alicdn.com/tfs/TB1KwRTlh6I8KJjy0FgXXXXzVXa-225-75.png';
}
};
</script>
通过 Weex Playground 运行结果如下
具体分析下整个流程。结合插件层和核心渲染库来分析。
插件层流程
以 iOS 为例分析,Android 的过程是类似的。
渲染库流程
渲染命令的解析,最终通过调用 OpenGL ES 的方法或组合方法来实现 Context2D 和 WebGL 的效果,生成帧缓存,提交给 GPU 渲染,最后在绑定的 GLKView 视图上显示。
Context2D,需要实现诸如 GPath、GTexture、GTransform、GTriangulate 等来实现 Canvas 的渲染效果; WebGL 相对简单,WebGL1.0 的 API 基本都能与从 OpenGL ES2.0 找到与之相对应的 API;GCanvas 测试例子
下面给出一些 GCanvas 的案例。
GCanvas 与 H5 Canvas 性能对比
Android 平台,左边是 GCanvas,右边是 H5 Canvas。同屏渲染图片越多,性能差异越明显。
Hilo 2D
100条鱼
基于 Hilo 2D 动画库,满屏鱼的动画测试。
Chart 图标渲染
Chart 图标库的渲染效果
基于图表库,不同类型的图表渲染测试。
附:GCanvas API 支持情况
最后附上 GCanvas Contex2D 和 WebGL API 的支持列表,支持常用的接口。API 覆盖情况请参考官网内容。
详见官网链接: Context2D 和 WebGL
.article-entry ol, .article-entry ul { list-style-position: outside; }题图:https://unsplash.com/photos/y3KZwM_nBTQ By @Trevor Paterson
文章来源:
Author:Taobao FED
link:http://taobaofed.org/blog/2017/07/27/gcanvas/