Canvas 动画引擎解析与微信小程序中的应用

1
腾讯云TVP行业顶级大咖交流分享经验
4
腾讯产业互联网学堂热门学习路径,0基础上手
  • 1
    关注“腾讯产业互联网学堂”公众号加群互动有好礼相送
  • 2
    向学习君回复口令“canvas”
  • 3
    加入TVP专家交流群,获得课程福利
腾讯产业互联网学堂微信公众号
“腾讯产业互联网学堂”微信公众号

讲师简介

章小飞

前端技术专家/ 腾讯云最具价值专家(TVP)

网名大漠穷秋,前端开发技术专家,先后使用并研究过 Flex、jQuery、Extjs、Backbone、AngularJS等常见的前端开发框架。先后著、译有《Ext 江湖》《ActionScript3.0 游戏设计基础》《用 AngularJS 开发下一代 Web 应用》( 2013 年最佳引进技术图书)《迈向Angular2》等书籍。对技术拥有无限热情,热爱分享,曾在30多家企业,多个线上和线下大会进行过前端技术的宣讲和传播。

简介

在开发微信小程序的过程中,我们经常需要展现一些图形和图表。目前市面上有好几款常用的图形库,在这些图形库的底层都有渲染引擎在支撑。 ZRender 是其中一款非常优秀的 Canvas 动画引擎,它也是 ECharts 图表库底层的渲染引擎。 本课程将会为你解析 ZRender 引擎中的基本设计思路和核心模块,带你充分理解 Canvas 引擎的核心原理。当你理解了这些内容之后,就可以自己扩展 ZRender 引擎来实现你想要的功能了。

讲义

抗击疫情,腾讯云在行动。在开发微信小程序的过程中,我们经常需要展现一些图形和图表。目前市面上有好几款常用的图形库,在这些图形库的底层都有渲染引擎在支撑。 ZRender 是其中一款非常优秀的 Canvas 动画引擎,它也是 ECharts 图表库底层的渲染引擎。

本次腾讯产业互联网学堂大咖分享课程邀请 腾讯云最具价值专家TVP 章小飞 分享关于“Canvas 动画引擎解析与微信小程序中的应用”课程的内容。

作者简介:章小飞 腾讯云最具价值专家(TVP)/ 前端技术专家。网名大漠穷秋,先后使用并研究过 Flex、jQuery、Extjs、Backbone、AngularJS等常见的前端开发框架。先后著、译有《Ext 江湖》《ActionScript3.0 游戏设计基础》《用 AngularJS 开发下一代 Web 应用》( 2013 年最佳引进技术图书)《迈向Angular2》等书籍。对技术拥有无限热情,热爱分享,曾在30多家企业,多个线上和线下大会进行过前端技术的宣讲和传播。

本次分享内容:

1、Quark Renderer 引擎可以用来做什么?

2、Canvas、SVG和WebGL

3、人们一直在追求 60 fps 的极致体验

4、requestAnimationFrame 与动画帧算法

5、Quark Renderer 引擎的整体结构

6、动画系统

7、渲染系统

8、事件系统

9、多引擎切换(Canvas \ SVG)

10、构建和发布 Quark Renderer

11、接下来做什么?

12、源码和参考资料链接

13、Q&A环节

我跟大家一样,在工作的过程当中经常想去阅读别人的源代码,因为大牛老师们说,如果你想自己进步快,就去阅读一些比较优秀的开源项目的源代码,我就听信了他们的话好多次想尝试阅读代码,前端、Java、Linux等,然后很快就发现读不下去。就像下图所描述的场景一样,相信大家都遇到过这样的情况。

后来我经历的次数多了后,逐渐理解这件事了。发现阅读别人的代码本质上是一种逆向工程,我们所看的别人的代码,实际上就像一座已盖好的大楼,就像下图,大家看到了大楼的外观灯火辉煌,很雄伟的一个模样,但实际上要把这栋大楼看懂的话是不容易的,因为我们不是这栋大楼的设计者。通过看大楼的外观,去看到大楼到底是怎么设计的,把它变成设计的蓝图是比较难的,这是为什么阅读别人的代码总是比较难的一个原因。

那么我了解到这件事之后,想重新尝试曾经想读的项目代码,重新开始读它,在读的过程中,我就会使用一些新的方法,比如一边读一边画图,就好像我也是一个设计师或者架构师,就好像这个项目是我自己设计的、写的。那么我把它的蓝图画出来,然后一步一步去不停的往前走,一点一点完善它。我发现这样做有点起色了,所以把这过程也分享给你们。

市面上有大量的开源项目,像GitHub或国内的gitee上面有很多的开源项目。很可惜的是里面有大量的开源项目实际上并没有提供这种设计蓝图。这就依赖于我们自己去分析它。如果我们没有这种设计蓝图,或者自己不去把这个图画出来的话,就好像进入了迷宫,在代码的迷宫里花费了很多的时间,很多的精力,最终还是不得不放弃,或者是看不到这个项目最精华的部分或是一个全貌,就是所谓的big picture是看不到的。

一、Quark Renderer 引擎可以用来做什么?

今天给大家演示两个案例,一个是浏览器环境里面的运行效果,另一个是在微信小程序里面的运行效果。最后我还有一个node-canvas环境的演示效果,因为这里面现在一个还有比较严重的bug,那我在下一次讲的时候,第3个演示的案例就会出来,今天给大家演示两个。Quark Renderer目前本身还处于开发的状态,我自己给它定的版本号目前是1.0.14,我会尽快把它第1个版本发布出来,在发布前我会把所有的恶心的地方都磨平,把example都写好。接下来给大家演示效果。(观看)

Canvas 在微信小程序中的问题,要重点注意的有两个地方:

第1个,在微信小程序中 Canvas 动画性能比较差,在真机运行的时候性能是很差的,不要去启动,一启动话基本上就没办法看了,卡成PPT那样,最多能跑到20Fps就是20帧每秒,大概就这样,这是最好的情况。

第2个,安卓的机器现在好像还是不能调试,这是我看到他们在开发者的社区上面的回复,1月7号的时候,安卓机还是没有办法调试Canvas API。

二、ZRender 引擎的整体结构

有人给了benchmark的一个测试的结果,如下图。你当然也可以自己去跑benchmark,市面上有好多工具可以帮你去做,也可以自己写脚本做测试,实际上就是跑分。测试的结果大概是在巨大量的对象的情况下,就是在Canvas里渲染很多的图形对象情况下,它的性能是比不上SVG渲染器,这是给出来的一个结果。

目前市面上典型的底层渲染技术就三个,Canvas、SVG和WebGL。

Canvas的优点是,性能比较高;各种平台的支持都很好,我给大家列出来的三个就是浏览器、node-canvas 、微信小程序,当然也包括其他各种小程序了,因为小程序它内部本质上都是嵌入了浏览器的引擎的内核;第三方的包,各种各样的库有很多。

缺点是,没有一些内置的基础设施,比如说事件系统是没有的,给大家演示一个事件的例子看(点击),整个的事件处理过程需要自己封装出来,Canvas是没有提供的,它只是一个用来操作像素的很底层的API,提供的API是非常贴近于底层的,它上层的比较好用的暴露给开发者调用的API并没有封装得很好。它内部是没有同时拖多个对象,这样一些机制都是没有提供的,需要你自己封装出来,或是借助于第三方的开源库来封装,这是Canvas是本身的一个特征。

SVG的优点是,在巨大量(百万级)的对象渲染场景下,性能是比较高。它所提供的那些接口比Canvas稍微好一点点,但也没有好到哪里去,有好多地方还是比较难看的,就比较死的那种API接口。它们类似的地方,就是Canvas好多的方法的签名和SVG基本是一样的,API接口的名字基本上都是一样的,也就是说如果你以前用过SVG,那么你来做Canvas还是比较快的,包括以前还有一个很古老的东西叫VML,它跟SVG是一起的,现在比较年轻一点的开发者,基本上都没有听说过VML,它是微软的一个技术,它实际上跟SVG是用来竞争的。

WebGL的优点是,支持3D,在3D下做得是非常好的,官方宣称它的性能非常高,但实际上从我使用的各种基于WebGL的东西来看,它耗资源是非常多的,消耗CPU和内存都很多。Google Earth是可以调出WebGL的引擎的,它支持3D的场景的渲染,你可以打开任务管理器去看,实际上你一旦开始用这些基于WebGL的东西,就会发现你的CPU或者显卡的使用率就会上去。所以实际上它的性能并不是它宣称的那么高。

主流的几款渲染引擎

基于Canvas、SVG、WebGL,我了解的有这么几款,可能大家了解的更多。

第1个是比较著名的three.js它的特色就是用来画一些3D的东西,非常的强大,它里面提供了好多的场景和demo,如果你们在做的业务里面有好多需要做3D的模型,可以尝试一下用three.js进行渲染,这个还是不错的开源的引擎。

第2个是也比较著名的D3,这个里面它也提供了巨多的例子,但是请大家特别注意坑比较多,从我自己使用的情况来看它的坑点在哪里,一个就是它的API不是那么的优美和一致,它一致性不是那么好。比如说你用你做一些饼图,做一些柱状图或者做一些散点散裂或者是气泡图的时候,他传递参数是一种方式,其他另外一些图形它就用另外一种方式去传参数,所以感觉上比较粗放。

第3个是Fabric.js,也是一个非常著名的开源渲染引擎,它的特点就是说它的原代码写得非常优美,因为我在读源码的过程中,我也在阅读发备课它的源代码,如果大家感兴趣,可以自己去GitHub上找到它,你会发现它整个的项目的结构,文件的命名,变量的命名,还包括它的注释,都写得非常的优美。以后如果我有时间,我也会来带大家解析Fabric.js的整个的设计思路,包括它的代码写法。

这是市面上的渲染引擎可能还有更多,现在给大家讲ZRender引擎,是ECharts提供的,跟上面的这些引擎相比,引擎本身它的影响力没有那么大,但是ECharts是很火的,大家都知道,但是ECharts底层的ZRender引擎没有其他引擎那么火,这是一个事实的描述,大家可以去了解。

三、人们一直在追求 60 fps 的极致体验

先说一下基本的动画的过程。所谓的动画实际上就是对象的视觉属性,就是可以看到的那些东西,在时间轴上随着时间变化的过程,比如说它的空间上的位置、尺寸大小、形状、颜色、纹理等,这就是视觉属性,就是人的眼睛能看到的那些属性,它随着时间的一个变化的过程,这就是动画的基本的一个过程。

有一些基本的参数需要大家理解,首先人的眼睛的视觉的暂留时间大概是100~400毫秒。这是伦敦大学的一个教授叫皮特.马克.罗葛特,他在1824年的时候发现了这样一个规律,就是人的眼睛有一个视觉的暂留现象。

这就告诉我们,一个物体只要每秒钟让它动10次,就是不需要在非常短暂的时间里面不停的动,只要每秒钟动10次,也就是10FPS,人类的眼睛就会认为这个对象是连续运动,实际上本身并不是那么连续。这也是后来有电影、动画的一个前提,因为那种古老的胶片电影,实际上就是24帧,一秒钟放24个,那人的眼睛就认为它是一个连续的画面。

很明显帧频率越高,画面的表现就越细腻。比如说我不是每秒钟放10帧,而是每秒放20帧、30帧、60帧,那画面就越细腻,动作越细腻。一般普通的动画,它的帧频大概是12Fps,就一秒钟放12帧就可以了,像蜡笔小新、火影忍者这种比较传统的动画,基本上12帧就可以了。那也有一些变态的动画它可以做得更细腻一点,比如说新海诚的系列,它把帧频调的更高,让整个画面表现更细腻,里面一些动画、物体的运动和细腻,那么普通的这种电影的胶片放映机,就是以前老的那种胶片放映机,一般都是24帧。

那相对于我们现在的现代的一些场景来看,比如大型的游戏吃鸡这种,一般大家都在追求60FPS,但是很少有人能达到。大家要注意,60FPS是一个理想的状况,所有人在追求,但一般来说很难达到。它的原因是这样子的,如果每秒要播60帧的话,那算下来一针就只有16.7毫秒的渲染时间,也就说要渲染一帧的画面,必须在16.7毫秒里渲染完,否则一秒钟就渲染不到60帧,那这就对硬件设备提出了更高的要求,GPU、存储器、运算能力,特别现在有专用的这种显卡了,显卡要足够好,比如玩吃鸡的桌面端版本,那么如果显卡不是很好的话,实际上画面是差的,体验很不好。

那么对于我们这种开放式这种接口来讲,要做到60FPS基本上就难如登天,特别是移动端,那像微信小程序基本上能做到极致,也就是30帧,30FPS。那么这是我们需要了解的一些基本的参数。

大家看下图,吃鸡的桌面端游戏,如果帧频很低的话,实际上你看到的画面是比较糊的,因为它来不及渲染很多的细节出来,下图中右边的图是在15帧的情况下,左边的图是17帧,可以看到地面、前面的人,还有树木,看得出来这种效果和表现形态都完全不同,如果只有15帧的话,就是比较糊的,来不及渲染那么多的细节出来。

现在移动端的GPU实际上也是越来越厉害。大家可以看到苹果的GPU还是很厉害的,有一些国产的手机也把GPU提得很高,就导致现在可以在手机上玩吃鸡、王者荣耀等这样的游戏。

那这实际上在好多年前是不可想象的,比如说在5年之前你是不可想象说手机上还可以玩像吃鸡这样的大型游戏,因为那时手机本身的硬件配置还是比较渣的,各种硬件还很贵,然后系统调优本身也没有做得很好。那在以后的话,相信移动端的硬件会越来越厉害,会有各种各样更新更便宜更小型化,性能更高的硬件设备出来,以后肯定是会越来越好,这是手机上的情况。

下图是Quark Renderer 的 benchmark一个效果,我已经给大家看过了,再run一下benchmark的效果。我这里面给的全部是1000个,待会拿到这个代码后,可以把它调你自己的机器上去调,你看你的机器能跑到多少,你可以把这里面的参数调成2000或者1万,你看它渲染的时间是多少?很简单,你只要改一个数字就好了,不需要改其他的代码。

给大家解释一下,这过程都体现了一些什么样的结果,如下图所示,这里面基本上都是在16.7毫秒以下,也就意味着在一帧的时间里面,可以渲染1000个图形对象出来,所有的图形对象还是都在动的,全部是有带动画的,都不停的在动,我们在不停的更新,它的位置都在动。那也就是说基本上在浏览器环境里面,用Quark Renderer来渲染1000个元素是非常轻松的,不会卡。

我这画面一点都不卡,大家能看出来吧,感觉还是比较流畅,但也不是说非常细腻的情况,但还是很流畅的,不会有卡顿的感觉。那也就说整个的一帧的时间里面能渲染出所有的对象,这是我测的结果。

第2个例子是,来看动画的性能,它的瓶颈点在哪里?我给大家跑这个例子,我这里放1万个,同时在这一个开发室里面渲染1万个对象,然后同时还让这1万个对象都在动,全部动起来。

大家可以看一下,有一点点小卡顿的感觉,但是整体上看还是比较流畅,只是有一点迟钝的那种感觉,但并不是说已经卡了没法看了。大家可以看帧频,我这边大概是10帧,好的时候可以到12针,那一般来讲最差的性能的点大概也就在12针。这是我在这里面测到的数据,大家在做其它场景的时候,你里面在做Canvas动画或者其他动画也好,如果帧率已经降到了12以下,基本上就不行了,至少要到12,要到20帧,20帧就已经基本上能接受了,就可以用了,如果能做到30帧的话,基本上就比较流畅了。

有一些人在玩吃鸡的时候,他的机器可能比较挫一点,那可能也就三四十帧,已经可以玩大型的吃鸡游戏了,所以如果你在开发时能做到20帧基本就可以了,那么到12针就属于可用的,所以像这个场景下面我跑1万个五角星,然后同时让他再动,那12帧可以。有人说你可不可以优化,现在已经没有办法去优化,这已经跟底层的接口跟硬件有关系,那有一个优化的点是,如果在你的业务场景里面,你并不是要同时让所有的对象全部在动,因为有些对象是不动的,并不需要说让1万个东西全部在动,没有什么必要场景下需要让1万个东西全部在动,基本上就不太容易出现这种场景,这是一个小概率的场景,所以它的帧率会上升得很多,比如说只有两个三个对象再动,其他对象都是静止的,这时它的帧率一下就上升了。

四、requestAnimationFrame 与动画帧算法

requestAnimationFrame 这方法出现前,做动画的时候,经常会看到有人去用JS定时器去做动画,这其实很简单,大家都写过前端代码,你只要一个setTimeInterval就可以了,你写一个定时器,然后移动位置,不停的设置对象的X和Y值,比如说是 Top和left这样两个值,不断的去把它+1,这个对象就在屏幕上面动了。例如,我给他一个16,假装这个地方能做到60FPS,实际上是达不到的,这实际上是有问题的,JS脚本动画,首先它有性能比较差的毛病,有两个原因导致的。

第1个就是定时器Timer实际上精度是不够的,因为Timer本身是由浏览器去出发的,那实际上浏览器有可能达不到这精度,或者它有一个偏差值,并不能达到16毫秒精度,有时候多一点,有时候少一点,那就会造成一定的怎么样?不是那么稳定,这是他第1个Timer的精度是不够的。

第2个,如果你是用这种定时器动画去操作DOM的话,实际上效率就更差了,大家都知道DOM操作是很贵的,会引起repaint和refollow,就是重绘和重排,那这样性能就更差了,所以基本上现在没有人会去用JS定时器去做动画,再怎么差也得用一个CSS3提供的路子去做动画。

所以我们后面就有了一个新的接口,叫requestAnimationFrame,那目前市面上主流的这些渲染引擎都是基于最底层的接口去做的,它的核心的代码是这样子,看下图。

在做一帧的时候,比如说step这个方法,往前走一步,那到最后再来调request再把我们本身代码存进去,相当于形成了看起来好像一个递归的样子。那么这个方法本身是由浏览器内核来调度的,浏览器内核会根据它的运行的情况来调度你的方法,也就说会确保你的方法在下一次浏览器渲染页面之前会被得到调用,它只确保,但是时间并不是固定的。

请大家注意requestAnimationFrame并不是时间固定的一个长度,也就是说并不一定能达到16.7毫秒,虽然在W3C的官方规范里面,说能够支持到60fps,也就是16.7毫秒这个方法会被调用一次,但真正运行时会发现肯定不行的,调不了这么多。比如说你在运行一些比较耗时的这种脚本,或者在做一些很复杂的操作,那基本上有可能达到100毫秒甚至200毫秒都有。

requestAnimationFrame目前浏览器支持的情况,基本上chrome、Edge、Firefox和opera都已经支持得非常好了,在很低的版本里面就已经支持,但是写法稍微有点不一样,也就是说这个方法在现有的主流浏览器里面是完全支持的,所以不用担心浏览器这种问题,一些很低版本浏览器,包括IE在内,都已经支持了。

在requestAnimationFrame里,怎么去用这个方法,它在这里有一块核心的代码,如下图所示,是在GlobalAnimationMgr这个类里面去使用的,我带你来阅读源代码了,这是核心的机制。在animation包里面这里有一个全局的动画管理器,会去负责引擎内部所有的动画的管理和调度,是这样一个设计。那这里面最关键的部分是在nextFrame这个方法。

五、Quark Renderer 引擎的整体结构

来看整体的结构,它分成这么几个子系统,首先是动画系统、渲染、事件、基本形状接口、Canvas渲染器,SVG渲染器,实际上ZRender以前还提供了VML的渲染器,我把它删掉了,删掉的原因是,因为现在IE的市场份额已经很小了,所以没有必要再去兼容VML,删掉后,体积大概可以缩小100K,还是比较值得的,当然里面可能还有一些部分可以删掉,我会尽快把它清理干净,让包尽量的小。

下图是Quark Renderer核心的模块之间的引用关系或者调用关系,看起来有点复杂了,这一页就不说了,回头我可以写一些详细的解释的文章来给大家解释这些是什么样的关系。

六、动画系统

来看子系统,首先是动画系统,来看它的设计模型或叫概念模型,这是比较重要的,就是要能读懂这个代码,要能看到背后的设计思路,才能读得懂它,如果你光看代码的话是很难的,就像开头的那张图,如果没有设计蓝图,别人不告诉你他是怎么想的,怎么设计的,你自己要从代码去猜,会消耗很多的时间,所以我先给大家说概念模型。

Quark Renderer概念模型是我从原来ZRender里,把它做了一个重构,它原来没有这么明确,用这个模型来给大家讲设计的概念模型,首先任意的一个元素,你在屏幕上看到的任意的东西都叫元素,一个星星、一个球、一张图、一段文字,那对于Quark Renderer渲染引擎来讲,它都是一个元素。那这些元素里有好多的属性,每个元素上面都有,比如说它当前的位置、缩放的状态、颜色、阴影、渐变等可视的属性。

每个属性都会被映射到一个轨道上去,比如说它的position在一个轨道上,scale、style也是,那实现的时候就这样实现了,可是scale和style都放在一个独立的轨道上面,每个轨道都有自己一根独立的时间线,时间线上面有好多的关键帧,叫Key Frame。对于调用者来讲,只要告诉引擎,你希望关键帧在哪里就行了,中间的这一个过程是引擎在运行过程当中自己去算的。

那在真正实现的时候是谁在算我们的时间线,在这地方有个叫Timeline时间线的类,他们也会去算,算的时候,里面实际上就只有一个核心的方法nextFrame。有人很好奇怎么算的,很简单。比如说当前的时间是多少,那么总体的时间的偏移量是多少,根据调用者给定的这样一个持续时间,叫diration,在算动画持续的时间,可以算到在任意的一个时刻上,这对象应该处于哪个位置上,所以中间的变化的过程就让它去算。

这个是动画系统它的概念模型,你一定要理解这个模型,才能真正去理解引擎它本身的一个状况。

再来看这个里面的类的设计,整个所有跟动画相关的这些实现都放在MSN包里,这些类似是主体的,比如说AnimationFrame,就是整个的一次动画过程,就是任意一个元素上面的一次完整的动画过程。一次动画过程里面可能有好多的轨道,有可能对象去变换它的位置、大小、样式,有时可能变换不多,只是变换它的位置,仅此而已,所以它有可能有多个轨道,那么一个轨道上面会有一个time line,那一个元素上面可以有多个AnimationFrame,可以在这个元素上面放好多个动画过程,把它写好的动画过程,但是每一个时刻只有一个动画过程在执行。

不可能同时让多个动画过程在执行,又那样的话,对象就到处乱跑了,那就不对了,时间线是互斥。这个是引擎的动画系统最核心的模型,但这里面有好多就是代码实现上面的小技巧,或者叫小把戏,自己去看就可以了,那些都不是特别的影响你阅读的,只要理解这个概念模型,对你来说阅读这个代码就非常简单。

七、渲染系统

一款渲染引擎最重要的就是渲染系统。首先渲染的系统是完全基于动画系统的,整个渲染系统都是构建的动画系统之上的,最重点的接口就是painter画笔对象,这个对象里面最有意思或者是最核心的代码在哪里?如下图所示,它会把整个需要备选的列表里面所有的对象全部拿出来,然后去检查是不是需要被渲染,再去调用它的渲染方法。

但是它里面最有意思或者最精华的部分在哪里?是在这里,如下图所示。

这个地方是控制了时间的,为什么要这么做?它的设计的思路是这样,如果一次渲染的对象非常多,比如说往引擎里面扔了1万个或者2万个对象,那很明显在16.7毫秒里面是没有办法把它全部渲染出来的,太多了,根本渲染不出来。不能一直卡在那边,在那边调用,如果你一直卡在那边的话,一帧的时间就会非常长,用户就感觉到明显的卡顿。

所以这边做了一个控制,就是说发现如果在这一次渲染的过程中,时间已经超过了整个调用的时间,已经超过了15毫秒,它就break掉,就退掉,然后等下一帧的时候再继续渲染。所以这边是做了一个很好的优化的点,这是最精华的一部分的代码。如果你要去阅读它的源代码,找到他最精华的部分。

那painter本身是由动画驱动的,也就说整个的渲染系统是由动画系统来驱动它渲染,但是设计本身我感觉还是有一点点的小问题,因为他把这两个东西就相当于紧紧的耦合在一起,我后面再想一下,看能不能把它给解开,对象本身的渲染的过程和动画的过程能不能解开,让它更好一些,我回头再看是不是能找到一个更好的设计的思路,但目前来看这个还是实现得不错。

增量渲染。我给大家演示一下,这很有意思,可以持续不断的去渲染,然后可以渲染出100万个对象出来。(点击观看大咖分享观看演示)

八、事件系统

事件系统也是比较有意思的一点,因为Canvas是一个很低级的很底层的API的接口,没有提供一些高层级的这种封装,那就意味着你要去做一些事件的时候就很麻烦,必须自己实现。

那么整个Quark Renderer的事件系统是完全模拟DOM事件的设计,整个的概念图在W3C的官方的网站上面是有Web里面的DOM事件,它的整个传递的方式,包括他传播,还有冒泡,一直到Target这整个的过程,完全模拟这个过程的,为什么要模拟,因为Canvas是没有内置,只能自己去写,先看我们写出来的系统,它的一个效果怎么样,给大家演示两个例子,然后给你看代码里面比较精华的部分,不说特别细致。(点击观看大咖分享 观看演示)

事件系统里比较精华的部分在哪里,我们来看它的包,所有跟事件相关的东西,我都已经把它全部重构到了Eventful.js的包里。

你也可以把它看成一个高层的接口,这里面提供了类似于JQuery的那一套API,比如说可以在一个对象上面去可以off、绑定事件、取消,事件绑定了,还可以只绑定一个等,就这样一些接口全把它模拟出来了,那么这是第1个最重要的接口。

第2个比较重要的接口就是代理,我们是见代理怎么去转发的,它的最核心的部分,这在我们到DomEventProxy就在这个事件代理的一个类里面,它做的事情很简单,就是把在外层的容器标签上面所能获取到的那些事件,把它全部拦截下来,然后转发到Canvas内部,也就说给他看这个代码,我拿一个例子演示。(阅读原文观看)

当然这个东西在微信小程序里面是有坑的,在哪里?还是刚才给大家看的,因为微信小程序里面没有办法操作DOM,也不让我们去拿到它外层的DOM的实力,所以这个时候就没有办法转发了,这个地方还是有一个不小的坑需要去填,就是说那些点击,还有那些按键,甚至touch的那些事件,没有办法被引擎给拦截到,那也就没有办法转发给开发室内部的这些对象,就没有办法去进行操作,这个坑还比较深,我得找时间看一看怎么能把它填起来,这样的话在微信小程序里面也能跟我们画出来的这样一些图员来进行交互。

九、多引擎切换机制(Canvas/SVG)

渲染器是可以支持多引擎切换的,ZRender实际上是做了三个引擎在里面的,有Canvas、SVG,、VML。VML我把它删掉,所以现在有两个,那这地方有两个重点的机制,它的设计的思路是这样的,他自己抽象了一套graphic图源这样的一些接口,比如说从Element元素、displayable、后image各种各样的图形元素,他抽了一大堆这样的东西出来。

那这些接口是跟底层的渲染技术是没有关系的,它既不是基于SVG,也不是基于Canvas等,但是它在设计的时候是参考了SVG和Canvas那一套提供的接口,它尽量的把两种这种渲染器,底层所封装的一些API,都体现在接口上面,所以它里面的一些方法的签名是一模一样的,这样保证它在真正去切换渲染引擎的时候能够少写一些代码,就是说能够保持设计思路的连贯性。

那么这里的这些接口是跟具体的渲染技术没有关系。真正在渲染的时候,会在初始化的时候去指定说需要哪个渲染引擎,是现在希望采用Canvas的方式去渲染,还是去使用SVG的方式,可以告诉他。那这是它的设计思路,在真正渲染的过程当中,每一个渲染的引擎都需要去提供一个painter画笔这样一个对象,是最核心的一个对象。

来看SVG它的渲染器,大家可以看到这个地方我们现在里面的图形都是在Canvas里,这是两种引擎的切换,这样的话就大概知道了Canvas整个的设计的思路。

十、构建和发布 Quark Renderer

第1件事情要把引擎本身代码拿下来,用git把它克隆下来,我已经把它放在上面,刻录下来之后,你直接NPM就可以了。jsduck这款文档的生成器,是我目前看到的市面上应该是到目前为止,生成出来最好看的一款文档生成器,它不需要你做什么,只要按照规范去写就可以了,它里面提供了53个标签的语法,那么这些标签的语法跟Java是一模一样的,你在代码里只要按照他的规范去写,就可以自动帮你把原代码里写的注释把抽出来,自动生成一个文档,还是比较好看,我们来给大家演示一个。(阅读原文进行观看)

如果你们公司里面刚好有一些前端的项目,没有找到很好看的文档的工具,推荐你尝试一下jsduck这样一款工具,它目前还是开源免费的,但是很可惜这个人已经放弃更新了,大概好多年前已经不再更新这个项目,但是它目前还是可用的,而且是免费的,在GitHub上面可以去找到,每次修改了一些用法或是版本,那就可以看到对应的文档的更新,不需要重新手写文档,是它自动根据我在里面写的注释把它抽出来的,但我会把这个注释完善一点。

发布的话是用NPM来publish,这大家都已经比较熟了,就不说了,我直接publish推一个版本上来。

十一、接下来做什么?

首先是把一些坑填平,比如说一些比较乱的代码,因为毕竟我是从别人的项目上面fork出来的,不是原初的作者,所以有很多地方我还是要按照我的一个思路来重构,叫改写也好,因为我会按照我的习惯来写。

第2个我会提供更多的代业务场景的使用的案例,因为现在好像讲的还是比较纯技术,我提供一些更多业务场景的案例是吧?我提供一些带业务场景的案例出来给大家看,比如说我打算做一些比如说思维导图或是流程图、实现表盘等,都可以在渲染引擎的基础上去做。

我会去做一些这样的案例出来,也许你们的某些场景会用到,但是我更希望把引擎本身的设计的思路讲给你,然后这样你们的公司里面有一些场景,是外面所有的开源项目都没有的时候,你就可以自己能做了,这是我想达到最终的一个东西。

第3个点就是我还想针对微信小程序再做一些优化,有一些比较深坑的地方,我希望至少能做到12Fps就能达到12帧,这样基本上就可以可用了。

我还会尽快去发布第1个正式的版本出来,当然接下来一段时间还会再讲几次,在填坑的过程当中一边填一边讲,也是帮我自己梳理思路。

十二、源码和参考资料链接

十三、Q&A环节

Q:目前的Canvas教程版本比较多,关于SVG的书会比较少,那么怎么系统学习SVG?

A:SVG的话在MTN上面有很多的资料,市面上SVG的书确实比较少,因为相对来讲SVG是一个比较古老的技术了,我手里有两本书是SVG,有一个很早以前好多年前的SVG开发实战,那么比较新一点的是一个两三年前应该是叫SVG精髓的这样一本书,如果你要的话,可以去看一下,他们是中文版,然后MTN上面有SVG的比较多的内容,你可以去看。

全部评论
讲师/助教

评论

直播日历