-
Notifications
You must be signed in to change notification settings - Fork 350
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
将你的 Virtual dom 渲染成 Canvas #32
Comments
很有创意,居然还可以这么玩 |
有兴趣可以一起来玩玩 |
很有意思,这个想法~ |
@guimeisang 哈哈,感觉蛮好玩的,我也只是实现了很基本的一些功能,做到后面就会越来越复杂。考虑的点就会更多~ 算是抛砖引玉吧。 |
react-konva可以了解下,实现思路“应该”和你差不多,并且渲染性能挺稳定的 |
@guimeisang 看了一下,很有参考价值!😊。后面可以考虑看看他的一些实现,或许有更好的帮助!🤔 |
@muwoo 可以的,拉我进入组织吧 |
@guimeisang 加我qq吧: 2424880409 |
的确是一种新的思路,感觉不错 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
项目概述
一个基于Vue的virtual dom插件库,按照Vue render 函数的写法,直接将Vue生成的Vnode渲染到canvas中。支持常规的滚动操作和一些基础的元素事件绑定。
github 地址: github
demo实例:demo
背景
从一个小的需求说起:某一天,产品提了一个这样的需求,需要制作一个微信活动页,活动页可以分享包含用户相关信息的图片。这些信息是需要从接口取的,而且每个人都不一样。第一次碰到这种需求的时候,基本上都会去手撸canvasAPI去做渲染功能,这种情况的步骤大致如下:
面临的主要问题是复用性太差,其次是性能上也有问题,用户看到的界面不一定和正式渲染出的界面一致,可能存在渲染差异。作为一个有追求的前端,当然得想想看有没有更好的法子。于是乎了解到了一个html2canvas 这样一个库。但是总是感觉还是要转成dom再去绘制,而且感觉性能和稳定性也不是很好。
我们知道vue通过vnode实现了对不同端的渲染工作,那有没有可能通过vnode实现对canvas的渲染呢?也就是说,没有vnode -> html -> canvas 而是直接vnode -> canvas。 同时利用vue的数据驱动,来达到绘制的数据驱动。想法有了,下面开始实施。
调研
这篇文章对此有详细的介绍:60 FPS on the mobile web 这里简单的概括一下:
看来canvas绘制页面的研究,很久之前就已经有人付出过研究了。而且性能还是很不错的。那我们更要试试看,到底我们的想法能不能实现了!越来越期待....
开始
canvas 的渲染其实也是一种尝试,既然前人以及做了充分的实践,那么我们便站在巨人的肩膀上去基于vue来实现一个数据驱动的canvas渲染。说做就做!(我们这里只提供思路,不做具体实现细节的讨论,因为实现起来有点复杂,如果有兴趣可以参考我的项目实现,或者一起交流探讨 )
处理vnode
熟悉Vue源码的应该都知道,Vue通过
render
函数,传入createElement
方法来构造出一个vnode
,通过发布--订阅
模式来实现对数据的监听,重新生成vnode
。我们要做的就是在vnode
这一层开始。所以,我们基于Vue源码的方式,实现一个监听函数,并混入Vue实例中:这样我们就可以愉快的在组件内部使用:
canvas 元素处理
render 的vnode我们需要做额外的一些约束,也就是说我们需要怎么样的渲染标签,来渲染对应的canvas元素(举个🌰):
其中这些元素类分别都继承于一个Super类,并且由于它们各有不同的展示方式,因此它们分别实现自己的draw方法,做定制化的展示。
绘制对象的布局机制实现
绘制 canvas 布局最基础的写法是为canvas 元素传入一系列坐标点和相关的基础宽高,这样写到实际项目中可能是这样的:
这样写确实有点不方便维护,目前有好几种解决方案,一种是使用
css-layout
去做管理。css-layout
支持的转换属性如下:这样也只是做了一层转换,帮我们更好的用css思维去写canvas,但是如果我们很不爽
css in js
的写法,其实我们还可以写一个webpack loader 来加载外部css:主要也就是将 css 文件转成
AST
语法树,之后再对语法树做转换,转成canvas
需要的定义形式。并以变量的形式注入到组件中。实现列表滚动
如果我们的元素很多,需要滚动时,我们必须解决
canvas
内部元素滚动的问题。这里我选择了使用Zynga Scroller 来模拟用户滚动方法,通过他返回的滚动坐标点,来对canvas进行重绘。详细的参考这里
事件模拟
对于
click,touch
等dom事件的模拟,我们采用的方案是根据点击区域进行检测,并找出最底层的元素,递归寻找父元素并触发对应事件处理程序,从而模拟事件冒泡。详细的实现可以参考这里
最后
canvas绘制页面也是一种创新的尝试,希望这里的研究对你有启发,也欢迎您的PR。这里也做了很多性能优化,限于篇幅不在赘述了,有兴趣也可以一起探讨。
最后:它并不意味着完全取代基于DOM的渲染,这仍然需要文本输入,复制/粘贴,可访问性和SEO。
出于这些原因,我们可以使用canvas和基于DOM的渲染的组合。
The text was updated successfully, but these errors were encountered: