highCharts转PNG/JPG/PDF等格式,不用在线转换,本地高效率/java

这两天实习的时候要求做后台服务器监控性能报告,需要将这些数据用发送邮件的方式发送html到指定管理员手中.但是还是不够完善,需要用图表表示出来更加直观.

但是html邮件也有缺陷,服务器会屏蔽JavaScript,无法运行,所以只能本地生成图片,然后html嵌入图片发送出去

生成指定图表的模块已经封装好可以直接调用运行.

github地址:https://github.com/yanweijia/highChartsToPNG

如果不了解highCharts的可以使用搜索引擎自行搜索,这里不再多赘述,直接上干货

代码在最下方

手动调试生成图表:直接用cmd切换当前目录并执行以下命令即可 具体命令格式:

phantomjs highcharts-convert.js -infile value.json -outfile chart1.png -width 1000 -constr Chart -resources highcharts.js,jquery.js

其中

highcharts-convert.js 指的是导出服务器文件 -infile value.json 为图表配置文件,可以是 .json 文件,也可以是 svg 文件 -outfile charts1.png 输出文件,后缀必须为.jpg, .png .pdf 或者 .svg. -scale 缩放比例,例如 图表宽度为 600px ,设置缩放为 2的情况下,输出的文件宽度为 1200px -width 输出文件宽度,设置该属性将会覆盖 scale 的值 -constr 图表类型,可以是:Chart、StockChart、Map -callback 图表回调函数,设置该函数将会在图表构造完毕后执行

重要:

请勿更改highcharts-convert.js文件 已经在官网文件的基础上将682行更改为fileList = params.resources.split(‘\,’); 具体更改原因请参考 http://stackoverflow.com/questions/38294099/highcharts-and-phantomjs-error-cant-find-variable-highcharts

 

json的格式还请自行到官网查看,此文章给出三个常用例子,分别是 条形统计图,饼图,还有面积图

柱状统计图(横向) 三组数据的例子 { chart: { type: 'bar' }, title: { text: '主标题' }, subtitle: { text: '副标题' }, xAxis: { categories: ['列名1', '列名2', '列名3', '列名4', '列名5'], title: { text: '纵坐标轴标题' } }, yAxis: { min: 0, title: { text: '横坐标轴标题', align: 'high' }, labels: { overflow: 'justify' } }, tooltip: { valueSuffix: ' millions' }, plotOptions: { bar: { dataLabels: { enabled: true } } }, legend: { layout: 'vertical', align: 'right', verticalAlign: 'top', x: -40, y: 80, floating: true, borderWidth: 1, backgroundColor: ((Highcharts.theme && Highcharts.theme.legendBackgroundColor) || '#FFFFFF'), shadow: true }, credits: { enabled: false }, series: [{ name: '组数据1名称', data: [107, 31, 635, 203, 2] }, { name: '组数据2名称', data: [133, 156, 947, 408, 6] }, { name: '组数据3名称', data: [1052, 954, 4250, 740, 38] }] } chart1饼图,带百分比 { chart: { plotBackgroundColor: null, plotBorderWidth: null, plotShadow: false, type: 'pie' }, title: { text: '主标题' }, tooltip: { pointFormat: '{series.name}: <b>{point.percentage:.2f}%</b>' }, plotOptions: { pie: { allowPointSelect: true, cursor: 'pointer', dataLabels: { enabled: true, format: '<b>{point.name}</b>: {point.percentage:.2f} %', style: { color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black' } } } }, series: [{ name: 'Brands', colorByPoint: true, data: [{ name: '数据1', y: 56.33 }, { name: '数据2', y: 24.03, sliced: true, selected: true }, { name: '数据3', y: 10.38 }, { name: '数据4', y: 4.77 }, { name: '数据5', y: 0.91 }, { name: '数据6', y: 0.2 }] }] } chart2面积图 { chart: { type: 'areaspline' }, title: { text: '标题' }, legend: { layout: 'vertical', align: 'left', verticalAlign: 'top', x: 150, y: 100, floating: true, borderWidth: 1, backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColor) || '#FFFFFF' }, xAxis: { categories: [ '横坐标数据1', '横坐标数据2', '横坐标数据3', '横坐标数据4', '横坐标数据5', '横坐标数据6', '横坐标数据7' ] }, yAxis: { title: { text: '纵坐标轴标题' } }, tooltip: { shared: true, valueSuffix: ' units' }, credits: { enabled: false }, plotOptions: { areaspline: { fillOpacity: 0.5 } }, series: [{ name: '曲线标题', data: [3, 4, 3, 5, 4, 10, 12] }] } chart3

代码目录结构:

根目录下有两个重要目录,分别是highcharts目录src目录,

其中highcharts(README文件有说明)放的是phantomjs,使用phantomjs(webkit内核,截图原理)可以利用文章最上方命令运行js文件生成图表.

src目录下面的cn.yanweijia.highCharts包下面分别是三个文件

JSONInfo.java  三个图表的json数据封装,可以直接传递相应标题数据参数并生成json数据

test.java 主函数,用来测试的类

Tools.java 将json文本写入到文件,执行cmd命令生成图片并打开.

 

注:复制代码时请将中文空格替换为制表符或英文空格,因wordpress会自动取消空格缩进所以才使用中文空格

Tools.java主要代码:

/**
* 写到文本文件
* @param str 文件内容
*/
public static void writeToTextFile(String str){
FileWriter fw = null;

try {
fw = new FileWriter(“I:/webpage.html”,false);
fw.write(str);
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 写到文本文件
* @param str 文件内容
*/
public static void writeToTextFile(String filePath,String str){
FileWriter fw = null;

try {
fw = new FileWriter(filePath,false);
fw.write(str);
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/*
* 执行命令
*/
public static boolean execCMD(String cmd){
try {
Runtime.getRuntime().exec(“cmd /c ” + cmd);
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
/*
* 执行命令,完成后返回
*/
public static boolean execCMDuntilFinished(String cmd){
BufferedReader br = null;
try {
Process p = Runtime.getRuntime().exec(“cmd /c ” + cmd);
br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
sb.append(line + “\n”);
}
System.out.println(sb.toString());
} catch (Exception e) {
e.printStackTrace();
return false;
}finally{
if (br != null)
{
try {
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
return true;
}

  JSONInfo.java文件:

package cn.yanweijia.highCharts;

/**
* <strong>如对json数据格式有问题请看项目根目录下面的highCharts文件夹里面的README文件</strong>
* @author 严唯嘉
* @func 自动生成highCharts统计图表使用的json数据
*/
public class JSONInfo {

/**图表主标题*/
public static final String TITLE_MAIN = “#title”;
/**图表副标题*/
public static final String TITLE_SUB = “#subTitle”;
/**水平坐标标题*/
public static final String TITLE_HORIZONTAL = “#horizontalTitle”;
/**垂直坐标标题*/
public static final String TITLE_VERTICAL = “#verticalTitle”;
/**数据坐标轴列名,用逗号’,’分隔开,如 ‘列名1′,’列名2′,’列名3’ */
public static final String NAME_AXES = “#axesNames”;
/**数据组标题*/
public static final String NAME_GROUPNAME = “#groupName”;
/**数据,用逗号’,’分隔开 如 123,124,125*/
public static final String DATA = “#data”;

/**条形统计图*/
public static final String CHART_BAR = “{chart: {type: ‘bar’},title: {text: ‘title’},subtitle: {text: ‘#subTitle’},xAxis: {categories: [#axesNames],title: {text: ‘#verticalTitle’}},yAxis: {min: 0,title: {text: ‘#horizontalTitle’,align: ‘high’},labels: {overflow: ‘justify’}},tooltip: {valueSuffix: ‘ millions’},plotOptions: {bar: {dataLabels: {enabled: true}}},legend: {layout: ‘vertical’,align: ‘right’,verticalAlign: ‘top’,x: -40,y: 80,floating: true,borderWidth: 1,backgroundColor: ((Highcharts.theme && Highcharts.theme.legendBackgroundColor) || ‘#FFFFFF’),shadow: true},credits: {enabled: false},series: [{name: ‘#groupName’,data: [#data]}]}”;
/**饼图*/
public static final String CHART_PIE = “{chart: {plotBackgroundColor: null,plotBorderWidth: null,plotShadow: false,type: ‘pie’},title: {text: ‘#title’},subtitle: {text: ‘#subTitle’},tooltip: {pointFormat: ‘{series.name}: <b>{point.percentage:.2f}%</b>’},plotOptions: {pie: {allowPointSelect: true,cursor: ‘pointer’,dataLabels: {enabled: true,format: ‘<b>{point.name}</b>: {point.percentage:.2f} %’,style: {color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || ‘black’}}}},series: [{name: ‘Brands’,colorByPoint: true,data: [#data]}]}”;
/**面积统计图*/
public static final String CHART_AREA = “{chart: {type: ‘areaspline’},title: {text: ‘#title’},legend: {layout: ‘vertical’,align: ‘left’,verticalAlign: ‘top’,x: 150,y: 100,floating: true,borderWidth: 1,backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColor) || ‘#FFFFFF’},xAxis: {categories: [#axesNames]},yAxis: {title: {text: ‘#verticalTitle’}},tooltip: {shared: true,valueSuffix: ‘ units’},credits: {enabled: false},plotOptions: {areaspline: {fillOpacity: 0.5}},series: [{name: ‘#groupTitle’,data: [#data]}]}”;

/**
* 获取面积图的JSON表示.其中非数组项可以为null,默认为空白字符串.
* @param mainTitle 图表标题
* @param verticalTitle 图表垂直坐标标题
* @param groupTitle 数据名称
* @param names 每个点对应的名称 ‘列1′,’列2′,’列3′,’列4′,’列5’
* @param datas 每个点对应的值 如 ,1,2,3,4,5
* @return
*/
public static String getAreaChartJSON(
String mainTitle,
String verticalTitle,
String groupTitle,
String[] names,
double[] datas){
String nameStr = “”, dataStr = “”;
if(mainTitle == null)
mainTitle = “”;
if(verticalTitle == null)
verticalTitle = “”;
if(groupTitle == null)
groupTitle = “”;
//将数组替换成目标格式
int length = names.length<datas.length?names.length:datas.length;
for(int i = 0 ; i < length – 1 ; i++){
nameStr += “‘” + names[i] + “‘,”;
dataStr += datas[i] + “,”;
}
nameStr += “‘” + names[length – 1] + “‘”;
dataStr += datas[length – 1];

String result = JSONInfo.CHART_AREA;
result = result.replaceAll(JSONInfo.TITLE_MAIN, mainTitle);
result = result.replaceAll(JSONInfo.TITLE_VERTICAL, verticalTitle);
result = result.replaceAll(JSONInfo.NAME_GROUPNAME,groupTitle);
result = result.replaceAll(JSONInfo.NAME_AXES,nameStr);
result = result.replaceAll(JSONInfo.DATA, dataStr);

return result;
}

/**
* 获取饼图的JSON表示,其中非数组参数mainTitle和subTitle可空
* @param mainTitle 主标题
* @param subTitle 副标题
* @param names 饼图的各个扇区名称
* @param datas 各个扇区数据
* @return json表示
*/
public static String getPieChartJSON(
String mainTitle,
String subTitle,
String[] names,
double[] datas){
if(mainTitle == null)
mainTitle = “”;
if(subTitle == null)
subTitle = “”;
//生成数据域
String dataStr = “”;
int length = names.length<datas.length?names.length:datas.length;
for(int i = 0 ; i < length – 1 ; i++){
dataStr += “{name:'” + names[i] + “‘,y:” + datas[i] + “},”;
}
dataStr += “{name:'” + names[length – 1] + “‘,y:” + datas[length – 1] + “}”;
String result = JSONInfo.CHART_PIE;

//开始用真实数据替换
result = result.replaceAll(JSONInfo.TITLE_MAIN, mainTitle);
result = result.replaceAll(JSONInfo.TITLE_SUB, subTitle);
result = result.replaceAll(JSONInfo.DATA, dataStr);

return result;
}

/**
* 获取条形统计图(横放的柱状)的JSON表示,其中,非数组的参数可空
* @param mainTitle 图表标题
* @param subTitle 图表副标题
* @param horizontalTitle 图表水平(横坐标)标题
* @param verticalTitle 图表垂直(纵坐标)标题
* @param axesNames 数据坐标轴列名数组,如 列名1,列名2…
* @param groupName 该系列类型 如 水果统计图就写 水果
* @param data <strong>double</strong>放数据的数组
* @return json数据
*/
public static String getBarChartJSON(
String mainTitle,
String subTitle,
String horizontalTitle,
String verticalTitle,
String[] axesNames,
String groupName,
double[] data){
String result = JSONInfo.CHART_BAR;
if(mainTitle == null)
mainTitle = “”;
if(subTitle == null)
subTitle = “”;
if(horizontalTitle == null)
horizontalTitle=””;
if(verticalTitle ==null)
verticalTitle = “”;
if(groupName == null)
groupName = “”;
//将传递进来的数组转换为目标格式,逗号分隔
String axesNamesStr = “” , dataStr = “”;
int length = axesNames.length<data.length?axesNames.length:data.length;
for(int i = 0 ; i < length – 1 ; i++){
axesNamesStr += “‘” + axesNames[i] + “‘” + “,”;
dataStr += data[i] + “,”;
}
axesNamesStr += “‘” + axesNames[length – 1] + “‘”;
dataStr += data[length – 1];

//替换数据
result = result.replaceAll(JSONInfo.TITLE_MAIN, mainTitle);
result = result.replaceAll(JSONInfo.TITLE_SUB, subTitle);
result = result.replaceAll(JSONInfo.TITLE_HORIZONTAL, horizontalTitle);
result = result.replaceAll(JSONInfo.TITLE_VERTICAL, verticalTitle);
result = result.replaceAll(JSONInfo.NAME_AXES, axesNamesStr);
result = result.replaceAll(JSONInfo.NAME_GROUPNAME, groupName);
result = result.replaceAll(JSONInfo.DATA, dataStr);

return result;
}

}

test.java测试文件:

/**
* 测试
*
* @param args
*/
public static void main(String[] args) {
//获取程序运行根目录
String relativelyPath=System.getProperty(“user.dir”);
relativelyPath += “\\highCharts\\”;
getAreaChart(relativelyPath);  //生成面积图并打开

//getPieChart(relativelyPath);  //生成饼图并打开

//getBarChart(relativelyPath);  //生成条形统计图并打开

  }

/**
* 测试面积统计图
* @param path highcharts目录路径
*/
public static void getAreaChart(String path){
String mainTitle = “主标题”;
String verticalTitle = “奖金”;
String groupName = “月份”;
String[] names = {“一月”,”二月”,”三月”,”四月”,”五月”,”六月”};
double[] datas = {1.1,10.20,15.45,45.85,11.23,6.25};
Tools.writeToTextFile(path + “test.json”, JSONInfo.getAreaChartJSON(mainTitle, verticalTitle,groupName, names,datas));
Tools.execCMDuntilFinished(path + “phantomjs ” + path + “highcharts-convert.js -infile ” + path + “test.json -outfile ” + path + “chartTest.png -width 1000 -constr Chart -resources ” + path + “highcharts.js,” + path + “jquery.js”);
Tools.execCMD(“start ” + path + “chartTest.png”);
}

参考资料:

如何将highcharts图表本地用命令导出图片 http://bbs.hcharts.cn/forum.php?mod=viewthread&tid=989

发表评论

电子邮件地址不会被公开。 必填项已用*标注