node-canvas模块是在node中实现canvas渲染的一种方式。可结合Echarts等应用于服务端生成图片流,进行图片处理等,如导出word或pdf时根据数据动态生成图片并嵌入文档中。下面将以Echarts为例,由服务端生成图片。
安装方式与npm包一致:
npm install canvas // or yarn add canvas
但是,node-canvas包依赖于Cairo等,需要先在系统中安装相关依赖。
OS | Command |
---|---|
OS X | brew install pkg-config cairo libpng jpeg giflib |
Ubuntu | sudo apt-get install libcairo2-dev libjpeg8-dev libpango1.0-dev libgif-dev build-essential g++ |
Fedora | sudo yum install cairo cairo-devel cairomm-devel libjpeg-turbo-devel pango pango-devel pangomm pangomm-devel giflib-devel |
Solaris | pkgin install cairo pkg-config xproto renderproto kbproto xextproto |
对于El Capitan用户而言,在安装相关依赖时可能会出错,还需要执行xcode-select --install
。同时,使用brew
安装时,会提示/usr/local/var
无权限创建的问题,可以通过如下命令解决:
mkdir /usr/local/var
sudo chmod -R 777 /usr/local/var
Linux下安装时可能会出现由于gcc、g++版本过低而无法编译node-canvas的问题,此时需要升级gcc、g++,升级办法详见此处。GCC中国镜像可以使用中科院镜像。
首先,需要安装Echarts包:
npm install echarts // or yarn add echarts
由于node-canvas默认不支持中文字体,所以需要导入中文字体文件,以华文仿宋为例,下载对应的ttf文件至项目目录,以便后续导入canvas。
由于项目后台使用Egg.js框架,所以通过extend的方式扩展application,相应代码如下:
// app/extend/application.js
'use strict';
const path = require('path');
const Canvas = require('canvas');
const echarts = require('echarts');
const fs = require('fs');
module.exports = {
generateImage (options, savePath, size) {
return new Promise((resolve, reject) => {
const canvas = new Canvas(parseInt(size.width,10), parseInt(size.height,10));
const font = new Canvas.Font('华文仿宋', path.join(__dirname, '华文仿宋.ttf'));
const ctx = canvas.getContext('2d');
ctx.addFont(font);
ctx.font = '12px 华文仿宋';
echarts.setCanvasCreator(function () {
return canvas;
});
const chart = echarts.init(canvas);
options.animation = false;
options.textStyle = {
fontFamily: '华文仿宋',
fontSize: 12,
};
chart.setOption(options);
try {
fs.writeFileSync(savePath, chart.getDom().toBuffer());
console.log("Create Img:" + savePath);
} catch (err){
console.error("Error: Write File failed" + err.message);
}
resolve();
})
}
}
通过此种方式即可在savePath
目录生成相应的图片文件。对于图片流(base64编码)而言,则只需要将chart.getDom().toBuffer()
改成chart.getDom().toBuffer().toString('base64')
,并直接resolve即可。