<dependency> ????<groupId>org.apache.commons</groupId> ??<artifactId>commons-exec</artifactId> ??<version>1.3</version></dependency><dependency> ???<groupId>com.github.abel533</groupId> ???<artifactId>ECharts</artifactId> ???<version>3.0.0.2</version></dependency><dependency> ???<groupId>com.google.code.gson</groupId> ???<artifactId>gson</artifactId></dependency><dependency> ???<groupId>com.github.abel533</groupId> ???<artifactId>ECharts</artifactId> ???<version>3.0.0.2</version></dependency>
,2,创建要用的js(echarts-convert.js)
function Base64() { ???// private property ???_keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; ???// public method for encoding ???this.encode = function (input) { ???????var output = ""; ???????var chr1, chr2, chr3, enc1, enc2, enc3, enc4; ???????var i = 0; ???????input = _utf8_encode(input); ???????while (i < input.length) { ???????????chr1 = input.charCodeAt(i++); ???????????chr2 = input.charCodeAt(i++); ???????????chr3 = input.charCodeAt(i++); ???????????enc1 = chr1 >> 2; ???????????enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); ???????????enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); ???????????enc4 = chr3 & 63; ???????????if (isNaN(chr2)) { ???????????????enc3 = enc4 = 64; ???????????} else if (isNaN(chr3)) { ???????????????enc4 = 64; ???????????} ???????????output = output + ???????????_keyStr.charAt(enc1) + _keyStr.charAt(enc2) + ???????????_keyStr.charAt(enc3) + _keyStr.charAt(enc4); ???????} ???????return output; ???} ???// public method for decoding ???this.decode = function (input) { ???????var output = ""; ???????var chr1, chr2, chr3; ???????var enc1, enc2, enc3, enc4; ???????var i = 0; ???????input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); ???????while (i < input.length) { ???????????enc1 = _keyStr.indexOf(input.charAt(i++)); ???????????enc2 = _keyStr.indexOf(input.charAt(i++)); ???????????enc3 = _keyStr.indexOf(input.charAt(i++)); ???????????enc4 = _keyStr.indexOf(input.charAt(i++)); ???????????chr1 = (enc1 << 2) | (enc2 >> 4); ???????????chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); ???????????chr3 = ((enc3 & 3) << 6) | enc4; ???????????output = output + String.fromCharCode(chr1); ???????????if (enc3 != 64) { ???????????????output = output + String.fromCharCode(chr2); ???????????} ???????????if (enc4 != 64) { ???????????????output = output + String.fromCharCode(chr3); ???????????} ???????} ???????output = _utf8_decode(output); ???????return output; ???} ???// private method for UTF-8 encoding ???_utf8_encode = function (string) { ???????string = string.replace(/\r\n/g,"\n"); ???????var utftext = ""; ???????for (var n = 0; n < string.length; n++) { ???????????var c = string.charCodeAt(n); ???????????if (c < 128) { ???????????????utftext += String.fromCharCode(c); ???????????} else if((c > 127) && (c < 2048)) { ???????????????utftext += String.fromCharCode((c >> 6) | 192); ???????????????utftext += String.fromCharCode((c & 63) | 128); ???????????} else { ???????????????utftext += String.fromCharCode((c >> 12) | 224); ???????????????utftext += String.fromCharCode(((c >> 6) & 63) | 128); ???????????????utftext += String.fromCharCode((c & 63) | 128); ???????????} ???????} ???????return utftext; ???} ???// private method for UTF-8 decoding ???_utf8_decode = function (utftext) { ???????var string = ""; ???????var i = 0; ???????var c = c1 = c2 = 0; ???????while ( i < utftext.length ) { ???????????c = utftext.charCodeAt(i); ???????????if (c < 128) { ???????????????string += String.fromCharCode(c); ???????????????i++; ???????????} else if((c > 191) && (c < 224)) { ???????????????c2 = utftext.charCodeAt(i+1); ???????????????string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); ???????????????i += 2; ???????????} else { ???????????????c2 = utftext.charCodeAt(i+1); ???????????????c3 = utftext.charCodeAt(i+2); ???????????????string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); ???????????????i += 3; ???????????} ???????} ???????return string; ???}}///////////////////////////////////system = require(‘system‘); // 获取参数var jspath = system.args[0];var base64JsonStr = system.args[1];//将base64解密var paramsJsonStr = ?new Base64().decode(base64JsonStr) ;//转换为json对象var jsonObj = JSON.parse(paramsJsonStr);var option = jsonObj.opt ;var width = jsonObj.width ;var height = jsonObj.height ;var outfile = jsonObj.outfile ;var fileSuffix = jsonObj.type ;function Convert(params){ ???this.params = params ; ???this.external = { ???????JQUERY3 : ?‘jquery-1.9.1.min.js‘, ???????ECHARTS3 : ‘echarts3.8.5.min.js‘ ???}; // 外部js ???this.page = require(‘webpage‘).create(); // 客户端 ???this.page.onConsoleMessage = function(msg, lineNum, sourceId) { ???????console.log(‘----console----‘+msg); ???}; ???var instance = this ; ???this.page.onError = function(msg, trace) { ???????var msgStack = [‘PHANTOM ERROR: ‘ + msg]; ???????if (trace && trace.length) { ????????????msgStack.push(‘TRACE:‘); ????????????trace.forEach(function(t) { ??????????????msgStack.push(‘ -> ‘ + (t.file || t.sourceURL) + ‘: ‘ + t.line + (t.function ? ‘ (in function ‘ + t.function +‘)‘ : ‘‘)); ????????????}); ????????} ???????console.error(msgStack.join(‘\n‘)); ???????instance.output("", false, msg); // 失败,返回错误信息 ???};}Convert.prototype.init = function(){ ???var instance = this ; ???instance.page.open("about:blank", function(status) { ???????// 注入依赖js包 ???????var hasJquery = instance.page.injectJs(instance.external.JQUERY3); ???????var hasEchart = instance.page.injectJs(instance.external.ECHARTS3); ???????// 检查js是否引用成功 ???????if (!hasJquery || !hasEchart) { ???????????output("Could not found " + external.JQUERY3 + " or " + external.ECHARTS3, false); ???????} ???????// 创建echarts ???????instance.page.evaluate(instance.createEchartsDom, instance.params); ???????// 定义剪切范围,如果定义则截取全屏 ???????instance.page.clipRect = { ???????????top : 0, ???????????left : 0, ???????????width : instance.params.width, ???????????height : instance.params.height ???????}; ???????// 渲染 ???????var result = instance.render(); ???????// 成功输出,返回图片或其他信息 ???????instance.output(result, true); ???});}Convert.prototype.render = function(){ ???var instance = this ; ???switch (instance.params.type) { ???case ‘file‘: ???????// 渲染图片 ???????instance.page.render(instance.params.outfile); ???????return instance.params.outfile; ???case ‘base64‘: ???default: ???????var base64 = instance.page.renderBase64(‘PNG‘); ???????return base64; ???}}Convert.prototype.output = function(content, success, msg) { ???var instance = this ; ???console.log(success ? "[SUCCESS]:" : "[ERROR]:" + content); ???instance.page.close(); ???instance.exit(instance.params); // exit};Convert.prototype.exit = function (params) { ???phantom.exit();};// // 创建eCharts Dom层 // @param params 参数 // ????????params.opt // ????params.width ????// ????params.height // ????params.outfile // ????params.type = ‘PNG‘ //Convert.prototype.createEchartsDom = function(params) { ???console.log("---createEchartsDom--"+params.width) ; ???var instance = this ; ???options = ?params.opt ; ???// 动态加载js,获取options数据 ???$(‘<script>‘) ???????.attr(‘type‘, ‘text/javascript‘) // .html(‘var options = ‘ + params.opt) ???????.appendTo(document.head); ???// 取消动画,否则生成图片过快,会出现无数据 ???if (options !== undefined) { ???????options.animation = false; ???} ???// body背景设置为白色 ???$(document.body).css(‘backgroundColor‘, ‘white‘); ???// echarts容器 ???var container = $("<div>") ???????.attr(‘id‘, ‘container‘) ???????.css({ ???????????width : params.width, ???????????height : params.height ???????}).appendTo(document.body); ???var eChart = echarts.init(container[0]); ???eChart.setOption(options);}//构建,入口new Convert(jsonObj).init();
3,Java代码
public class ImageRenderParams { ???//echart的Option ???public Option opt; ???//echart图片的宽度 ???public int width = 600; ???//echart图片的高度 ???public int height = 400; ???//echart图片保存地址 ???public String outfile = "d:/dsafdf.png"; ???//file 或者 ?PNG ???public String type = "file";}/** ????* 创建Echart图 ????* ????* @param imagePath 图片保存地址,例如:d:/demo.png ????* @throws Exception ????*/ ???public ImageResult createEchartImage(Option option) throws Exception { ???????if (option == null) { ???????????return new ImageResult(); ???????} ???????String imgPath = getRandomImagePath(option); ???????ImageRenderParams params = new ImageRenderParams(); ???????params.opt = option; ???????params.outfile = imgPath; ???????// 实例化 ???????Gson gson = new Gson(); ???????// 将map转成JSON ???????String paramsJsonStr = gson.toJson(params); ???????Base64 base64 = new Base64(); ???????//转换为base64编码是为了防止执行指令的时候出问题 ???????String base64Str = base64.encodeToString(paramsJsonStr.getBytes("UTF-8")); ???????//调用的JS文件路径 ???????File jsFile = ResourceUtils.getFile("classpath:static/js/echarts-convert.js"); ???????// 生成的图片名称 ???????String jsFilePath = jsFile.getAbsolutePath(); ???????String[] args = new String[3]; ???????args[0] = jsFilePath; ???????args[1] = base64Str; ???????// 执行脚本 ???????try { ???????????CommandExecUtil.phantomjsExec(args); ???????} catch (Exception e) { ???????????throw e; ???????} ???????return new ImageResult(imgPath); ???} ???public static class ImageResult { ???????private String imagePath; ???????private byte[] imageData; ???????public ImageResult(String imagePath) { ???????????this.imagePath = imagePath; ???????} ???????public ImageResult() { ???????} ???????public String getImagePath() { ???????????return imagePath; ???????} ???????public byte[] getImageData() throws Exception { ???????????if (StringUtils.isBlank(imagePath)) { ???????????????return null; ???????????} ???????????if (imageData != null) { ???????????????return imageData; ???????????} ???????????File file = ResourceUtils.getFile(imagePath); ???????????if (file == null) { ???????????????return null; ???????????} ???????????FileInputStream fi = new FileInputStream(file); ???????????imageData = new byte[fi.available()]; ???????????fi.read(imageData); ???????????fi.close(); ???????????return imageData; ???????} ???}
使用PhantomJS在服务器端渲染并生成Echarts图片
原文地址:http://blog.51cto.com/dengshuangfu/2130281