当前位置: 首页>编程语言>正文

Java后端+PhantomJS +Echars生成数据图表

这次遇到的问题要在发送email时,生成好看的数据图表,所以初步思路就是:java服务端+echars。由于echars是需要用js执行的,所以还需要加入执行环境PhantomJS?。

PhantomJS 是一个基于 WebKit 的服务器端 JavaScript API。原生支持各种Web标准:DOM处理,CSS选择器,JSON,Canvas,和SVG。PhantomJS可以用于页面自动化,网络监测,网页截屏,以及无界面测试等。

第一种方式是前端+echars,生成图表后,后台使用phantomjs进行进行截屏,这个方式我试了可行,但是增加了前端的工作量,丢掉。

下面这种方式,是利用PhantomJS 是一个js执行环境,通过拼凑出cmd的执行命令,把绘图所需要的数据,组装成echars需要的格式一并传入。即通过后台(Java)执行PhantomJS,调用echarts-convert.js+数据,并输出成图片。

①开发环境准备:

去git上下载echartsconvert,本次phantomjs.exe执行的就是echarts-convert.js,它引用了echarts.min.js和jquery-3.2.1.min.js。

下载phantomjs-2.1.1-windows。linux和mac有对应的版本,使用的时候配置phantomjs-2.1.1-windows\bin\phantomjs.exe的路径到cmd命令里就行。

Java后端+PhantomJS +Echars生成数据图表,第1张

②Demo:

public class EcharsServiceImpl implements EcharsService {

private static final String JSpath = "D:/AAAA/A/echartsconvert/script/echarts-convert.js"; //echarts.js的存放路径

private static final String phantomjs = "D:/AAAA/A/phantomjs-2.1.1-windows/bin/phantomjs.exe"; //PhantomJS的存放路径

public static void main(String[] args) {

String optiona =Constant.dd; //应用预先定义的测试数据,Constant.aa,bb,cc,dd,ee在后面给你们

generateEChart(optiona);

}

public static String generateEChart(String options) {

String dataPath = writeFile(options); //把参数放文件里落地

String path = "D:/AAAA/A/Echart/"+UUID.randomUUID()+".png";

try {

File file = new File(path);

if (!file.exists()) {?

File dir = new File(file.getParent());

dir.mkdirs();

file.createNewFile();

}

String blank = " ";

String cmd = phantomjs +blank+ JSpath + " -infile " + dataPath + " -outfile " + file;

Process process = Runtime.getRuntime().exec(cmd);

InputStream inputStream = process.getInputStream();

//System.out.println(inputStream.read()); ? 看一下流,输出-1就得检查一下前头的cmd了

BufferedReader input = new BufferedReader(new InputStreamReader(inputStream));

//String line = "";

//while ((line = input.readLine()) != null) {

//System.out.println(line);

//}

input.close();

} catch (IOException e) {

e.printStackTrace();

}finally{

return path;

}

}

/**

* 把数据写入文件,调试demo的时候,可以跳过这段,直接指定xxx.json

*/

public static String writeFile(String options) {

String dataPath="D:/AAAA/A/Echart/"+ UUID.randomUUID().toString().substring(0, 8) +".json";

try {

/* 写入Json文件 */

File writename = new File(dataPath); // 相对路径,如果没有则要建立一个新的output.txt文件

if (!writename.exists()) {? //文件不存在则创建文件,先创建目录

File dir = new File(writename.getParent());

dir.mkdirs();

writename.createNewFile(); // 创建新文件

}

BufferedWriter out = new BufferedWriter(new FileWriter(writename));

out.write(options);

out.flush(); // 把缓存区内容压入文件

out.close(); // 最后记得关闭文件

} catch (IOException e) {

e.printStackTrace();

}

return dataPath;

}

}

③测试数据准备

?测试数据要自己到echars的官网上找(https://echarts.baidu.com/examples/#chart-type-tree),每种图表的option不一样,单击下面不同类型的图进去,组装合适的option。组装的时候要记得修改key-value中value的单引号。

?我在下面的常量里准备了饼图、折线图、漏斗图、仪表盘四种简单数据。

Java后端+PhantomJS +Echars生成数据图表,第2张

/**

* 供echars模拟的数据

* @author PENGJING973

*/

public class Constant {

/**饼图*/

public static final String aa = "{tooltip:{trigger:'item',formatter:'{a} <br/>{b}: {c} ({d}%)'},legend:{orient:'vertical',x:'left',data:['直接访问','邮件营销','联盟广告','视频广告','搜索引擎']},series:[{name:'访问来源',type:'pie',radius:['50%','70%'],avoidLabelOverlap:false,label:{normal:{show:false,position:'center'},emphasis:{show:true,textStyle:{fontSize:'30',fontWeight:'bold'}}},labelLine:{normal:{show:false}},data:[{value:335,name:'直接访问'},{value:310,name:'邮件营销'},{value:234,name:'联盟广告'},{value:135,name:'视频广告'},{value:1548,name:'搜索引擎'}]}]}";

/**折线图 */

public static final String bb = "{\"title\":{\"text\":\"电流图\",\"subtext\":\"电流图\",\"x\":\"left\"},\"toolbox\":{\"feature\":{\"saveAsImage\":{\"show\":true,\"title\":\"保存为图片\",\"type\":\"png\",\"lang\":[\"点击保存\"]}},\"show\":true},\"tooltip\":{\"trigger\":\"axis\"},\"legend\":{\"data\":[\"邮件营销\",\"联盟广告\",\"视频广告\"]},\"xAxis\":[{\"type\":\"category\",\"boundaryGap\":false,\"data\":[\"周一\",\"周二\",\"周三\",\"周四\",\"周五\",\"周六\",\"周日\"]}],\"yAxis\":[{\"type\":\"value\"}],\"series\":[{\"name\":\"邮件营销\",\"type\":\"line\",\"stack\":\"总量\",\"data\":[120,132,101,134,90,230,210]},{\"name\":\"联盟广告\",\"type\":\"line\",\"stack\":\"总量\",\"data\":[220,182,191,234,290,330,310]},{\"name\":\"视频广告\",\"type\":\"line\",\"stack\":\"总量\",\"data\":[150,232,201,154,190,330,410]}]}";

/**漏斗图*/

public static final String cc = "{title:{text:'漏斗图(对比)',subtext:'纯属虚构',left:'left',top:'bottom'},tooltip:{trigger:'item',formatter:'{a} <br/>{b} : {c}%'},toolbox:{show:true,orient:'vertical',top:'center',feature:{dataView:{readOnly:false},restore:{},saveAsImage:{}}},legend:{orient:'vertical',left:'left',data:['产品A','产品B','产品C','产品D','产品E']},calculable:true,series:[{name:'漏斗图',type:'funnel',width:'40%',height:'45%',left:'5%',top:'50%',funnelAlign:'right',center:['25%','25%'],data:[{value:60,name:'产品C'},{value:30,name:'产品D'},{value:10,name:'产品E'},{value:80,name:'产品B'},{value:100,name:'产品A'}]},{name:'金字塔',type:'funnel',width:'40%',height:'45%',left:'5%',top:'5%',sort:'ascending',funnelAlign:'right',center:['25%','75%'],data:[{value:60,name:'产品C'},{value:30,name:'产品D'},{value:10,name:'产品E'},{value:80,name:'产品B'},{value:100,name:'产品A'}]},{name:'漏斗图',type:'funnel',width:'40%',height:'45%',left:'55%',top:'5%',funnelAlign:'left',center:['75%','25%'],data:[{value:60,name:'产品C'},{value:30,name:'产品D'},{value:10,name:'产品E'},{value:80,name:'产品B'},{value:100,name:'产品A'}]},{name:'金字塔',type:'funnel',width:'40%',height:'45%',left:'55%',top:'50%',sort:'ascending',funnelAlign:'left',center:['75%','75%'],data:[{value:60,name:'产品C'},{value:30,name:'产品D'},{value:10,name:'产品E'},{value:80,name:'产品B'},{value:100,name:'产品A'}]}]}";

/**仪表盘*/

public static final String dd ="{tooltip:{formatter:'{a} <br/>{c} {b}'},toolbox:{show:true,feature:{restore:{show:true},saveAsImage:{show:true}}},series:[{name:'速度',type:'gauge',z:3,min:0,max:220,splitNumber:11,radius:'50%',axisLine:{lineStyle:{width:10}},axisTick:{length:15,lineStyle:{color:'auto'}},splitLine:{length:20,lineStyle:{color:'auto'}},axisLabel:{backgroundColor:'auto',borderRadius:2,color:'#eee',padding:3,textShadowBlur:2,textShadowOffsetX:1,textShadowOffsetY:1,textShadowColor:'#222'},title:{fontWeight:'bolder',fontSize:20,fontStyle:'italic'},detail:{formatter:function(value){value=(value+'').split('.');value.length<2&&(value.push('00'));return('00'+value[0]).slice(-2)+'.'+(value[1]+'00').slice(0,2);},fontWeight:'bolder',borderRadius:3,backgroundColor:'#444',borderColor:'#aaa',shadowBlur:5,shadowColor:'#333',shadowOffsetX:0,shadowOffsetY:3,borderWidth:2,textBorderColor:'#000',textBorderWidth:2,textShadowBlur:2,textShadowColor:'#fff',textShadowOffsetX:0,textShadowOffsetY:0,fontFamily:'Arial',width:100,color:'#eee',rich:{}},data:[{value:40,name:'km/h'}]},{name:'转速',type:'gauge',center:['20%','55%'],radius:'35%',min:0,max:7,endAngle:45,splitNumber:7,axisLine:{lineStyle:{width:8}},axisTick:{length:12,lineStyle:{color:'auto'}},splitLine:{length:20,lineStyle:{color:'auto'}},pointer:{width:5},title:{offsetCenter:[0,'-30%'],},detail:{fontWeight:'bolder'},data:[{value:1.5,name:'x1000 r/min'}]},{name:'油表',type:'gauge',center:['77%','50%'],radius:'25%',min:0,max:2,startAngle:135,endAngle:45,splitNumber:2,axisLine:{lineStyle:{width:8}},axisTick:{splitNumber:5,length:10,lineStyle:{color:'auto'}},axisLabel:{formatter:function(v){switch(v+''){case'0':return'E';case'1':return'Gas';case'2':return'F';}}},splitLine:{length:15,lineStyle:{color:'auto'}},pointer:{width:2},title:{show:false},detail:{show:false},data:[{value:0.5,name:'gas'}]},{name:'水表',type:'gauge',center:['77%','50%'],radius:'25%',min:0,max:2,startAngle:315,endAngle:225,splitNumber:2,axisLine:{lineStyle:{width:8}},axisTick:{show:false},axisLabel:{formatter:function(v){switch(v+''){case'0':return'H';case'1':return'Water';case'2':return'C';}}},splitLine:{length:15,lineStyle:{color:'auto'}},pointer:{width:2},title:{show:false},detail:{show:false},data:[{value:0.5,name:'gas'}]}]}";

}

④生成效果

分别修改第二步main方法中optiona 的值,等于Constant.aa,bb,cc,dd,ee,观察到D:\AAAA\A\Echart\文件夹下生成的json文件和png文件。

Java后端+PhantomJS +Echars生成数据图表,第3张

echars的js参考了这位前辈的csdn:https://blog.csdn.net/leftwukaixing/article/details/89449071,感谢!


https://www.xamrdz.com/lan/58x1848557.html

相关文章: