node-canvas后台生成图表

我们在开发智能问答系统时,希望能给用户更好的体验,其中一个功能是通过图表的方式展示给用户相关的数据,比如股票的K线图,股票的筹码分布图等等。最初在设计这个功能的时候设想是通过webview在原生的问答界面中展示H5开发的页面,但是发现出来的体验并不好。这里主要存在两个问题:

1. 首次加载时间较长,用户会看到空白的网页;

2. 上下滚动查看历史问答记录时,需要重新加载H5页面,用户会感觉到窗口一闪一闪

第一个问题没有办法,毕竟在没有缓存的情况下加载和渲染的时间就是那么多,通过交互动画可以暂时解决这个问题,但是第二个问题很头疼,我们尝试了优化缓存机制,将H5页面缓存到本地,当webview组件刷新时原生框架拦截webview请求数据,将本地缓存的页面直接返回,但是效果并不好,造成窗口闪动的原因是webview渲染的速度较慢,当页面比较复杂时就会出现这种情况(这一点我们用一个最简单的只包含文字的页面测试验证了),而且webview有个很大的问题是内存占用较大,当窗口中包含太多webview组件时容易出现内存泄漏的问题,因此也无法通过缓存太多的webview组件来解决这个问题。

最后没有办法还是只能回归原生,但是原生开发简单的组件还好,比如简单的柱状图和折线图等图表,但是碰到复杂的组件如K线图等就很花时间了,本身我们的客户端开发就不是很够,所以我们转换了思路,既然卡片上面的东西大部分都是静态的,那能不能生成K线图的图片直接给客户端展示呢?关键是我们能不能找到一种方式生成图表的图片,而且速度还必须快(因为我们是问答系统,如果生成速度太慢体验也是很差)

一开始我们的思路是H5开发人员把页面开发好,然后通过PhantomJS直接后台渲染并输出保存成图片,但是这个方式有几个问题,一是并不是对所有的图表框架都能支持,比如AntV等,经常会报错,出来的图片经常和预期的不一样,二是速度很慢,拿AntV的一个F2的K线图Demo尝试了一下,要花1秒多的时间,这显然也是不能接受的(除了画图,我们还需要经过语义理解,构造数据等步骤,这样整个回答的时间要到2秒多)

然后我们就想到了HTML5提供的Canvas接口,在GitHub上面找到了node-canvas项目,那AntV的Demo试了一下,生成的图片完美达到我们的要求:出来的图片和预期的一致,并且速度很快,一张K线图只花了70多毫秒的时间。顺着这个思路,又有了新的问题:我们的图表并不是简单的一个K线图,可能还会包含一个柱状图或者雷达图,而诸如AntV和ECharts这类框架在初始化图表的时候要求传入的容器组件只能在一个图表组件中初始化,这样我们就没有办法组合两个组件了。所以我们选择了Konva框架,它是封装于node-canvas的一个高级绘画框架,在Canvas的基础上抽象了Layer的概念,我们在想,既然Canvas可以作为图表组件的初始化容器组件,那么Layer能不能达到同样的目的呢?于是我们搞了个Demo果然没问题,这样我们就可以通过初始化多个Layer并赋予不同的图表组件达到组合的目的。

我用EggJs,Konva和AntV的F2组件做了个Demo程序,有兴趣的可以参考一下

代码等过几天有时间再更新

你可能感兴趣的:(node-canvas后台生成图表)