node+echarts实现服务器端渲染可视化图表

近几年,随着大数据的兴起、浏览器性能的提升以及web前端技术的快速迭代,基于js的web前端数据可视化技术(D3、echarts 、highcharts、AntV等)成为了数据可视化领域的”当红炸子鸡”。数据可视化产品通常是To B的产品,这些js库最常使用的场景就是在客户浏览器端渲染展示可视化图表。但是如果要一次性创建上百张信息图表,在浏览器端渲染生成显然不科学,这就需要在服务器端使用后端语言(java、python等)预先渲染成图片。Node.js的出现将js的触角伸向了服务器端,这里探讨一下如何使用Node实现服务器端渲染可视化图表。

Node实现服务器端渲染可视化图表主要有两种方案:

第一种方案:使用流行的headless环境,也就是所谓的无头浏览器,包括puppeteer、headless chrome、PhantomJS等。通过node操作无头浏览器渲染可视化图表,并调用浏览器截图API把渲染的结果截图保存下来。

第二种方案:使用Node调用canvas模块直接在后端渲染可视化图表并保存。

废话不多说,直接撸代码。

————————–分割线————————–

第一种方案

headless环境选择Puppeteer,js可视化库选择echarts。Puppeteer是谷歌官方出品的一个通过DevTools协议控制headless Chrome的Node库,感兴趣可以去其官网详细了解一下。

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
50
51
52
53
54
55
56
57
58
59
//导入两个模块Puppeteer和path
const puppeteer = require('puppeteer');//npm install安装一下
const path = require('path');//Node内置模块
//定义渲染可视化图表并截图函数
const render = async(subject,arrData)=>{
// 启动浏览器
const browser = await puppeteer.launch({args: ['--no-sandbox'],timeout:0});
//创建空白页面
const page = await browser.newPage();
//定义网页模板
let htmlTemplate =
`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="canvas" style="width:1400px;height:800px"></div>
</body>
</html>`

//设置网页源码
await page.setContent(htmlTemplate);
// 传递数据到evaluate函数中,挂载到window对象的全局属性中
await page.evaluate((arrData)=>{
window.chart = {arrData:arrData}
},arrData);
//在网页中导入echarts库
await page.addScriptTag({
path: path.resolve(__dirname, '../public/js/echarts.min.js')
});

//在网页中导入可视化图表渲染代码
await page.addScriptTag({
content:`
(function (window) {
var option = {
//echarts配置项
//.....
};
var myChart = window.echarts.init(document.getElementById('canvas'));
myChart.setOption(option);
})(this);`
});
//对渲染后的图表截图
let canvas = await page.$('#canvas');
await canvas.screenshot({
type: 'jpeg',//默认png
quality:100,
path:path.resolve(__dirname, '../public/images/'+subject+".jpg")
});
// 关闭网页
await page.close();
// 关闭浏览器
await browser.close();
}

第二种方案

使用Node的canvas模块,js可视化库选择echarts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const canvas = require("canvas");//npm install canvas
const echarts = require("echarts");//npm install echarts
const fs = require('fs');//node内置模块,直接引入

//创建一个canvas实例
let ctx = canvas.createCanvas(800,600)
//将canvas实例设置为echarts容器
echarts.setCanvasCreator(()=>ctx)
//使用canvas实例为容器创建echarts实例
let chart = echarts.init(ctx)
//echarts配置项
let option = {
//....
}
//设置图标实例配置项
chart.setOption(option);
//保存图片
const imgPath = __dirname + '/bubble.png'
fs.writeFileSync(imgPath, chart.getDom().toBuffer());

相比第一种方案,第二方案更加快捷、高效,推荐使用第二方案。如果不想写这么多代码,有一个node-echarts
的模块可以拿过来直接用。

最后,来看下渲染结果(以散点图为例)。
散点图集合
散点图
perfect & 无懈可击!