利用PhantomJS搭建Highcharts export服务

时间:2021-08-14 23:19:38

一直在使用Highcharts做web图表的展示, 但是当发送定时的报表邮件的遇到了这个问题. 为了保证邮件图表和web页图表样式一致, 需要能原样生图. 这里考虑如下:

1. 如何生成jpg图片

在很久以前,官方推荐用Imagemagick将SVG转成jpg. 考虑如何得到SVG, 大量文档推荐用 nodejs+jsdom从json数据中生成svg. 在实际使用中,  Imagemagick和jsdom环节处理复杂的数据都非常孱弱, 复杂的图表丢东少西难看要死, 无法上线. 在google上纠结好久, 终于发现了这神器PhantomJS.

做测试这么久, 尽然不知道PhantomJS这种神器. 简单说, PhantomJS是个不显示UI的浏览器, 可以无GUI的server上使用. 而且核心为webkit, 轻松支持Highcharts等几乎所有的js库. 在本文中, PhantomJS拿来解决这个问题再合适不过. 只需要想办法把数据传给PhantomJS, 简单几句代码, 截个图就行了.

2. 数据传递

下面这个问题就是怎么把数据传给PhantomJS. PhantomJS支持命令行, 在服务器端, (一般为Java, Python, PHP),  与JS交互的最好数据格式就是JSON. 但是JSON数据比较大时, 直接用命令行就不行了.  传递方式可以选:

  1. fork子进程, 利用其stdin吐进去
  2. 生成一个json临时文件, 命令行指定该文件地址
  3. 利用PhantomJS的webserver模块单独开启一个服务, 向其POST

三种方式都可以, 看具体的需求. 第二种比较简单, 就是总要生成中间文件, 不是很喜欢....

还有一个问题, 利用JSON提供基本数据还可以, 但是传递控制显示样式的callback函数(比如formatter)比较麻烦. 如果所有图表样式统一还好说, 在PhantomJS脚本内写死就可以. 对于图表需要个性样式的情况, 目前想到的解决办法是, 将callback写成各个js文件, 在传递JSON时指定一个额外的配置, 确定读取哪个js文件, 然后再统一到一起.

 

这两个问题解决, 就可以直接从服务器端生成图片了. 

补充: 刚看到了官方的解决方案, 跟我想法差不多, 地址如下:

http://www.highcharts.com/component/content/article/2-news/52-serverside-generated-charts

而且在文章后半部, 指出了PhantomJS在数据点过多情况下的性能问题. 

稍有不同的是, 官方使用了命令行参数指定callback js文件, 并且callback是通过Highcharts强大的api来调整样式的. 而不是向本文一样做合并.