java生成echarts图片自动保存到本地(无页面浏览器渲染)

最近碰到一个导出word的功能,需要用到一些在前端展示的echarts图片,但是又不能手动去下载保存,经过查资料找到使用phantomjs可以将输入的js文件转成base64编码返回。

1、下载phantomjs
https://pan.baidu.com/s/14M-P83XCUcwl9dJBwctuJg?pwd=tznp
2、配置环境
1.1 环境配置

下载后解压文件到没有中文的目录下,点击  我的电脑-属性-高级系统设置-环境变量-系统变量-Path-编辑-新建-输入地址-保存

1.2 测试是否成功添加

找一个目录,cmd进入命令行,输入

phantomjs -v

出现版本号,说明配置正确

3、测试是否可用
3.1 测试phantomjs 命令是否可用 

进入解压的文件夹,文件夹下有个examples文件夹,其中有很多js文件,cmd进入命令行后输入以下命令测试phantomjs 是否可用

phantomjs hello.js

出现Hello,world!说明配置正确

4、编写代码
4.1 新建springboot项目

idea内新建springboot项目,这个不会的私信我[dog头][dog头]

4.2 添加依赖

后续需要将对象转成js文件,需要用到gson依赖,如果只是想测试,不需要添加任何依赖。

<dependency>
	<groupId>com.google.code.gson</groupId>
	<artifactId>gson</artifactId>
	<version>2.8.9</version>
</dependency>
4.3 编写测试代码
4.3.1 构造echartsOption.js文件,就是echarts的运行脚本

也可以自己去echarts官网上找个例子新建一个js文件就行

Examples - Apache ECharts

echartsOption.js文件可以直接放到echarts编辑器中运行看结果

option = {
    "title": {
        "text": "差异性分析",
        "subtext": "",
        "x": "left"
    },
    "legend": {
        "orient": "vertical",
        "left": "left",
        "bottom": "bottom",
        "show": true,
        "data": []
    },
    "tooltip": {
        "trigger": "item",
        "axisPointer": {
            "type": "shadow"
        },
        "textStyle": {
            "fontSize": 12
        }
    },
    "toolbox": {
        "show": true,
        "feature": {
            "saveAsImage": {
                "show": true
            }
        }
    },
    "grid": {
        "left": "3%",
        "right": "4%",
        "bottom": "35px",
        "containLabel": true
    },
    "xAxis": {
        "type": "category",
        "axisLabel": {
            "interval": 0,
            "rotate": 45,
            "textStyle": {
                "fontStyle": "normal",
                "fontWeight": "normal"
            }
        },
        "data": [
            "A",
            "B",
            "C",
            "D"
        ],
        "boundaryGap": true,
        "nameGap": 30,
        "splitArea": {
            "show": false
        },
        "splitLine": {
            "show": false
        }
    },
    "yAxis": {
        "axisLabel": {},
        "type": "value",
        "splitArea": {
            "show": true
        }
    },
    "series": [
        {
            "name": "质量区间",
            "type": "boxplot",
            "data": [
                [
                    106.34,
                    107.8125,
                    109.21,
                    110.4,
                    112.33
                ],
                [
                    106.98,
                    108.1775,
                    109.365,
                    110.1875,
                    111.9
                ],
                [
                    105.72,
                    107.515,
                    108.545,
                    110.5125,
                    113.65
                ],
                [
                    104.57,
                    106.6575,
                    107.825,
                    109.2575,
                    113.1574
                ]
            ],
            "tooltip": {}
        },
        {
            "name": "综合评价",
            "type": "line",
            "smooth": "true",
            "data": [],
            "z": 10
        }
    ]
}

4.3.2 编写java测试代码
import sun.misc.BASE64Decoder;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class TestEcharts {
    /**
     * echartsJs 路径
     */
    private static String ECHARTS_PATH = "F:\\work\\s\\echarts-convert\\echarts-convert.js";

    private static String OPTION_PATH = "F:\\work\\s\\echarts-convert\\echartsOption.js";

    private static String OUT_PATH = "E:\\time\\222\\java\\demo4\\src\\main\\resources\\";


    /**
     * echarts获取图片base64编码URL头
     */
    private static final String BASE64FORMAT = "data:image/png;base64,";

    public static void main(String[] args)throws Exception {
        BufferedReader input = null;
        String line;
        String base64 = "";
        try {
            /**
             * 命令格式:
             * phantomjs echarts-convert.js -infile optionURl -width width -height height
             * 可选参数:-width width -height height
             * 备注:
             * phantomjs添加到环境变量中后可以直接使用,这里防止环境变量配置问题所以直接使用绝对路径
             */
            String cmd = " phantomjs " + ECHARTS_PATH + " -infile " + OPTION_PATH
                    + " -width " + 800 + " -height " + 800;
            Process process = Runtime.getRuntime().exec(cmd);
            System.out.println(cmd);
            /**
             * 获取控制台输出信息
             * 通过JS中使用console.log()打印输出base64编码
             * 获取进程输入流,进行base64编码获取
             */
            input = new BufferedReader(new InputStreamReader(process.getInputStream()));
            while ((line = input.readLine()) != null) {
                if (line.startsWith(BASE64FORMAT)) {
                    base64 = line;//.replace(BASE64FORMAT, "");
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                input.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            //删除js文件
//            Files.delete(Paths.get(OPTION_PATH));
        }
        System.out.println(base64);
        getFileFromBase64(base64);
    }


    public static File getFileFromBase64(String base) throws Exception {

        String base64Pic = base;
        File file = null;
        Map<String, Object> resultMap = new HashMap<String, Object>();
        if (base64Pic == null||base=="") { // 图像数据为空
            resultMap.put("resultCode", 0);
            resultMap.put("msg", "图片为空");
        } else {
            BASE64Decoder decoder = new BASE64Decoder();
            String baseValue = base64Pic.replaceAll(" ", "+");//前台在用Ajax传base64值的时候会把base64中的+换成空格,所以需要替换回来。
            byte[] b = decoder.decodeBuffer(baseValue.replace("data:image/png;base64,", ""));//去除base64中无用的部分
            base64Pic = base64Pic.replace("base64,", "");
            SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd");
            String nowDate = df2.format(new Date());
            String imgFilePath = OUT_PATH + nowDate ;
            File file1 = new File(imgFilePath);
            if (!file1.exists() && !file1.isDirectory()) {//判断文件路径下的文件夹是否存在,不存在则创建
                file1.mkdirs();
            }
            try {
                for (int i = 0; i < b.length; ++i) {
                    if (b[i] < 0) {// 调整异常数据
                        b[i] += 256;
                    }
                }
                file = new File(imgFilePath + "\\" + System.currentTimeMillis()+".png");
                // 如果要返回file文件这边return就可以了,存到临时文件中
                OutputStream out = new FileOutputStream(file.getPath());
                out.write(b);
                out.flush();
                out.close();
            } catch (Exception e) {
                resultMap.put("resultCode", 0);
                resultMap.put("msg", "存储异常");
            }

        }
        return file;
    }
}

运行结果:

4.3.3 构造js文件

如何构造phantomjs 运行需要的js文件呢?

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class EChartsToJs {

    public static void main(String[] args) {
        // 创建 ECharts 的 option 对象
        ChartOption option = new ChartOption();

        // 模拟添加数据
        option.setTitle(new Title("规格差异性分析"));

        option.setTooltip(new Tooltip("item"));
        option.setxAxis(new XAxis(new String[]{"A",
                "B",
                "C",
                "D"}));
        option.setyAxis(new YAxis("value"));

        Series series = new Series();
        series.setName("箱线图");
        series.setType("boxplot");
        series.setData(new double[][]{
                {107.35, 108.02, 106.42, 108.14, 107.19}, 
                {108.2, 109.55, 109.7, 109.95, 108.95}, 
                {109.45, 106.33, 109.43, 107.99, 110.93}, 
                {110.05, 109.65, 108.9, 109.78, 109.08}
        });

        option.setSeries(new Series[]{series});

        //将 option 对象转换为 JSON
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        String jsonOption = gson.toJson(option);

        //将 JSON 写入到 JavaScript 文件中
        String jsFilePath = "E:\\3\\echarts\\echartsOption.js";
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(jsFilePath))) {
            writer.write("option = " + jsonOption + ";");
            System.out.println("ECharts option 已写入文件: " + jsFilePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 定义 ChartOption 类
    static class ChartOption {
        private Title title;
        private Tooltip tooltip;
        private XAxis xAxis;
        private YAxis yAxis;
        private Series[] series;


        public Title getTitle() {
            return title;
        }

        public void setTitle(Title title) {
            this.title = title;
        }

        public Tooltip getTooltip() {
            return tooltip;
        }

        public void setTooltip(Tooltip tooltip) {
            this.tooltip = tooltip;
        }

        public XAxis getxAxis() {
            return xAxis;
        }

        public void setxAxis(XAxis xAxis) {
            this.xAxis = xAxis;
        }

        public YAxis getyAxis() {
            return yAxis;
        }

        public void setyAxis(YAxis yAxis) {
            this.yAxis = yAxis;
        }

        public Series[] getSeries() {
            return series;
        }

        public void setSeries(Series[] series) {
            this.series = series;
        }
    }

    // 其余的类定义
    static class Title {
        private String text;

        public Title(String text) {
            this.text = text;
        }

        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
        }
    }

    static class Tooltip {
        private String trigger;

        public Tooltip(String trigger) {
            this.trigger = trigger;
        }

        public String getTrigger() {
            return trigger;
        }

        public void setTrigger(String trigger) {
            this.trigger = trigger;
        }
    }

    static class XAxis {
        private String[] data;

        public XAxis(String[] data) {
            this.data = data;
        }

        public String[] getData() {
            return data;
        }

        public void setData(String[] data) {
            this.data = data;
        }
    }

    static class YAxis {
        private String type;

        public YAxis(String type) {
            this.type = type;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }
    }

    static class Series {
        private String name;
        private String type;
        //        private int[][] data;
        private double[][] data;

        public void setName(String name) {
            this.name = name;
        }

        public void setType(String type) {
            this.type = type;
        }

        public void setData(double[][] data) {
            this.data = data;
        }

        public String getName() {
            return name;
        }

        public String getType() {
            return type;
        }

        public double[][] getData() {
            return data;
        }
    }
}

实际上以上代码都只是为了构造出phantomjs命令行运行所需的代码,实际还是命令行运行。

写在最后:

不设置什么vip可见,关注可见,因为我也是参考了一些其他的代码写出来的,就想为需要的人分享一下,希望对你有所帮助

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我不会编程呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值