• Highcharts导出图片


    概述:

    Highcharts是在做项目涉及到统计图的时候大家的首选,同时也会用到highcharts的export功能,将统计图导出为图片,刚好,最近也遇到了这样的事情,总结出来,以备后用。


    导出方式:

    highcharts导出图片实现有三种:highcharts服务器导出、局域网服务器导出、本地后台导出。

    首先,highcharts服务器导出是默认的导出方式,不需要任何操作,只需在chart中配置export参数即可,但是这种导出方式需要联网;

    其次,局域网服务器导出,需要在局域网内配置导出的服务器,可参考http://www.highcharts.com/docs/export-module/setting-up-the-server进行配置;

    最后,本地后台导出,既不需要联网,也不需要局域网服务器,直接在后台写对应的servlet即可,是本文讲解的重点内容。


    导出原理:

    Highcharts图表导出(或下载)本质上是将SVG代码转换为不同文件格式的过程,用到的工具是batik,所以所谓导出服务器,只不过是调用batik,将SVG代码转换并下载。参见下图:


    在Java中通过SVG生成图片的代码如下:

    package com.lzugis.demo;
    
    import java.io.FileOutputStream;
    import java.io.OutputStream;
    import java.io.StringReader;
    
    import org.apache.batik.transcoder.Transcoder;
    import org.apache.batik.transcoder.TranscoderException;
    import org.apache.batik.transcoder.TranscoderInput;
    import org.apache.batik.transcoder.TranscoderOutput;
    import org.apache.batik.transcoder.image.JPEGTranscoder;
    import org.apache.batik.transcoder.image.PNGTranscoder;
    
    public class CreateImg {
    	public static void main(String[] args) throws Exception {
    		String svg = "<svg height="200" xmlns="http://www.w3.org/2000/svg"><polygon points="10,10 75,150 150,60" style="fill:#63BCF7;stroke:black;stroke-3"/></svg>";
    		String type="image/png";	
    		String filename="svg";
    		if (null != type && null != svg) {
    			svg = svg.replaceAll(":rect", "rect");
    			String ext = "";
    		    Transcoder t = null;
    		    if (type.equals("image/png")) {
    				ext = "png";
    				t = new PNGTranscoder();
    		    } 
    		    else if (type.equals("image/jpeg")) {
    				ext = "jpg";
    				t = new JPEGTranscoder();
    		    }
    		    if (null != t) {
    		    	OutputStream out = new FileOutputStream("D:\"+filename+"."+ext);
    		    	TranscoderInput input = new TranscoderInput(new StringReader(svg));
    				TranscoderOutput output = new TranscoderOutput(out);
    				try{
    				    t.transcode(input, output);
    				    System.out.println("out");
    				} 
    				catch (TranscoderException e) {
    				    e.printStackTrace();
    				}
    		    }
    		}
    	}
    }
    生成后图片效果如下:



    在web中,servlet的编写代码如下:

    package com.lzugis.demo;
    
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    import java.io.StringReader;
    
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.batik.transcoder.Transcoder;
    import org.apache.batik.transcoder.TranscoderException;
    import org.apache.batik.transcoder.TranscoderInput;
    import org.apache.batik.transcoder.TranscoderOutput;
    import org.apache.batik.transcoder.image.JPEGTranscoder;
    import org.apache.batik.transcoder.image.PNGTranscoder;
    
    public class SaveAsImage extends HttpServlet {
    	private static final long serialVersionUID = 1L;
    	public SaveAsImage() {
    		super();
    	}
    
    	/**
    	 * Destruction of the servlet. <br>
    	 */
    	public void destroy() {
    		super.destroy(); // Just puts "destroy" string in log
    	}
    
    	public void doGet(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    		doPost(request, response);
    	}
    	
    	public void doPost(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    		request.setCharacterEncoding("utf-8");//设置编码,解决乱码问题
    		String type = request.getParameter("type");
    		String svg = request.getParameter("svg");
    		String filename = request.getParameter("filename");
    		filename = filename==null?"chart":filename;
    		ServletOutputStream out = response.getOutputStream();
    		if (null != type && null != svg) {
    		    svg = svg.replaceAll(":rect", "rect");
    		    String ext = "";
    		    Transcoder t = null;
    		    if (type.equals("image/png")) {
    				ext = "png";
    				t = new PNGTranscoder();
    		    } 
    		    else if (type.equals("image/jpeg")) {
    				ext = "jpg";
    				t = new JPEGTranscoder();
    		    }
    		    else if(type.equals("image/svg+xml")) 
    	            ext = "svg";   
    		    response.addHeader("Content-Disposition", "attachment; filename="+ filename + "."+ext);
    		    response.addHeader("Content-Type", type);
    		    
    		    if (null != t) {
    				TranscoderInput input = new TranscoderInput(new StringReader(svg));
    				TranscoderOutput output = new TranscoderOutput(out);
    				
    				try {
    				    t.transcode(input, output);
    				} catch (TranscoderException e) {
    				    out.print("Problem transcoding stream. See the web logs for more details.");
    				    e.printStackTrace();
    				}
    		    } else if (ext.equals("svg")) {
    		    	OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8");
    		    	writer.append(svg);
    		    	writer.close();
    		    } else 
    		    	out.print("Invalid type: " + type);
    		} else {
    		    response.addHeader("Content-Type", "text/html");
    		    out.println("Usage:
    	Parameter [svg]: The DOM Element to be converted." +
    		    		"
    	Parameter [type]: The destination MIME type for the elment to be transcoded.");
    		}
    		out.flush();
    		out.close();
    	}
    
    	/**
    	 * Initialization of the servlet. <br>
    	 *
    	 * @throws ServletException if an error occurs
    	 */
    	public void init() throws ServletException {
    		// Put your code here
    	}
    
    }
    web.xml中的servlet的配置如下:

      <servlet>
        <description>This is the description of my J2EE component</description>
        <display-name>This is the display name of my J2EE component</display-name>
        <servlet-name>SaveAsImage</servlet-name>
        <servlet-class>com.foxconn.highcharts.demo.SaveAsImage</servlet-class>
      </servlet>
    
      <servlet-mapping>
        <servlet-name>SaveAsImage</servlet-name>
        <url-pattern>/SaveAsImage</url-pattern>
      </servlet-mapping>
      <welcome-file-list>
        <welcome-file>basic_line.jsp</welcome-file>
      </welcome-file-list>
    在前台,调用的方式如下:

            var chart;
            $(document).ready(function(){
                Highcharts.setOptions({
                    lang: {
                        printChart:"打印图表",
                        downloadJPEG: "下载JPEG 图片" ,
                        downloadPDF: "下载PDF文档"  ,
                        downloadPNG: "下载PNG 图片"  ,
                        downloadSVG: "下载SVG 矢量图" ,
                        exportButtonTitle: "导出图片"
                    }
                });
                chart = new Highcharts.Chart({
                    chart: {
                        renderTo: 'container',
                        defaultSeriesType: 'line',
                        marginRight: 130,
                        marginBottom: 25
                    },
                    title: {
                        text: 'Monthly Average Temperature',
                        x: -20    //center
                    },
                    subtitle: {
                        text: '测试中文乱码',
                        x: -20
                    },
                    xAxis: {
                        categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                            'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
                    },
                    yAxis: {
                        title: {
                            text: 'Temperature (°C)'
                        },
                        plotLines: [{
                            value: 0,
                             1,
                            color: '#808080'
                        }]
                    },
                    exporting:{
                        enabled:true,
                        filename:'class-booking-chart',
                        url:'http://localhost:8081/HighChartsDemo/SaveAsImage'
                    },
                    tooltip: {
                        formatter: function(){
                            return '<b>' + this.series.name + '</b><br/>' +
                                    this.x + ': ' + this.y + '°C';
                        }
                    },
                    legend: {
                        layout: 'vertical',
                        align: 'right',
                        verticalAlign: 'middle',
                        borderWidth: 0
                    },
                    series: [{
                        name: 'Tokyo',
                        data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
                    },{
                        name: 'New York',
                        data: [-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5]
                    },{
                        name: 'Berlin',
                        data: [-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6, 17.9, 14.3, 9.0, 3.9, 1.0]
                    },{
                        name: 'London',
                        data: [3.9, 4.2, 5.7, 8.5, 11.9, 15.2, 17.0, 16.6, 14.2, 10.3, 6.6, 4.8]
                    }]
                });

    同样,如果不想将导出按钮不显示在图片上的话,你可以通过chart.getSVG()函数来获取到chart的svg元素,并以ajax的方式传给后台,代码如下:

                $("#export").click(function(){
                	var svg = chart.getSVG();
                	$.ajax({
                		type: "post",
                		url: 'http://localhost:8081/HighChartsDemo/SaveAsImage',
                		data:{
                			type:"image/png",
                			filename:"chart",
                			svg:svg
                		},
                		success: function(data){
                			console.log("success");
                		}
                	});
                });

    batik的lib包下载地址:http://pan.baidu.com/s/1dDwEvqL





  • 相关阅读:
    Vue 消息无缝滚动
    请求不携带cookie问题
    vue中添加favicon
    自定义表单-校验数据规则
    vue 刷新当前页面的方式
    读阮一峰《ECMAScript 6 入门》小结
    Java进阶知识点3:更优雅地关闭资源
    Java进阶知识点2:看不懂的代码
    用Java实现异构数据库的高效通用分页查询功能
    Java进阶知识点1:白捡的扩展性
  • 原文地址:https://www.cnblogs.com/lzugis/p/6539820.html
Copyright © 2020-2023  润新知