需求:
项目中大量用到了highchart图表,出于某些需求,需要将highchart图表导出为图片,以便于生成pdf、word等文档。
现有的解决方案:
highchart官方提供的导出方式是将图表数据发回其官网服务器,生成图片后返回,正常情况下系统不会允许使用这种方案。
网上找到一种自建导出服务器的方式来导出图表,大致思想是使用开源项目batik,将组成highchart图表的svg格式数据转换成指定的图片格式(png,jpg……)。但是整个服务很复杂,大概需要引入近19个jar包,单纯为导出图片,总觉得有点不值得……
使用谷歌前端开源工具canvg.js,将svg格式的图像完美转换至canvas中,利用canvas导出图表……
最终解决方案(当然是最后一种):
研究过highchart的都会注意到,其核心是根据数据配置操作svg格式的图像(svg:一种用xml定义的语言,用来描述二维矢量及矢量/栅格图像,具体请自行百度)。
而html5 canvas可以利用工具canvg.js将svg格式的图像精准转换至canvas画布中……
canvas图像提供了方便的图片转换功能
综上所述,
将highchart图表的svg数据提取出来
用canvg将svg数据转换到canvas中
使用canvas获取图片base64数据……
使用图表数据转换成图片
细节描述:
//1、提取highchart的svg数据
/*
* 使用jquery获取“基本的”svg数据(不建议使用);
* 这种方式获取的数据不能按照画布大小自动调节尺寸
**/
//var chartData = $("#container").find(".highcharts-container").html();
/*
* 使用highchart自带exporting.js中getSVG()方法获取(需引入exporting.js);
* 这种方式获取的数据较完整,或根据画布大小等因素自动适应,图表不会变形,渲染较好
**/
var chartData = $("#container").highcharts().getSVG();
//2、用canvg将svg数据转换到canvas中
/*
* @Param canvasId canvas标签的id
* @Param chartData 图表svg数据
* 需要在提前页面加载canvas标签(如:<canvas id='canvasId' style='……'></canvas>)
**/
canvg(canvasId, chartData);
//3、使用canvas转换图片……
/*
* 这里获取的是base64位的图片数据,也可以直接在浏览器中使用
* 将imgData转换正二进制编码,写入文件中成为图片(打算用java实现)
***/
var canvas = document.getElementById("canvasId");
var imgData = canvas.toDataURL("image/png");//这里获取的是png格式图片
//< img src ="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAlgAAAGQCAYAAAByNR6YAAA……可以直接在页面展示
'''
4、使用图表数据转换成图片
/*
* @Param imgPath 图片路径,包括导出图片名称
* @Param imgData 图片base64格式数据
*/
public void export(String imgPath, String imgData) {
BASE64Decoder decoder = new BASE64Decoder();
FileOutputStream out = null;
try {
//将base64数据转换成二进制数据
byte[] bytes = decoder.decodeBuffer(imgData);
for (int i = 0; i < bytes.length; ++i) {
if (bytes[i] < 0) {
bytes[i] += 256; //调整异常数据
}
}
out = new FileOutputStream(imgPath);
out.write(bytes);
out.flush();
out.close();
} catch (IOException e) {
log.debug("Export image Exception: ");
e.printStackTrace();
}
}
注:1、使用canvg.js需要rgbcolor.js图像颜色相关组件,如果系统中没有,请引入!
2、exporting.js的引入会使系统中图表增加官方默认的图片下载组件,我修改官方的 exporting.js,去除了默认的图片下载组件,保留了getSVG()方法