Highcharts 导出到 Word

需求:
1、分析报告中,使用 Highcharts 生产图表

2、导出分析报告到Word中,包括图表导出

 

难点/盲点分析:

1、前端的 Highcharts 是如何导出到图片的?
      解决方法:详细了解其API 和 工作原理;分析其自带的导出图片的功能,了解到是通过传 svg 到后台生成的,
 

2、前端如何获取 svg 提交到后台的图片?

 

      解决方法:java 有相关的 包 可以实现

 

3、当界面有多张图片的时候,如何显示?

 

      解决方法:图标渲染时或者提交的时候,通过调用 Highcharts 的getSvg() 获取各个图表的svg保存到隐藏域

 

以上也可以算是总结吧!我也是一步一步的分析出来的! 下面是我还原我的步骤:

 

我们首先分析 Highcharts  默认的导出功能的原理;是如何实现;

看下面的 exporting.js 导出js :

 

代码一:

w.exporting = {
        type: "image/png",
        url: "http://export.highcharts.com/",
        width: 800,
        buttons: {

  

代码二:

    e.post = function(a, b) {
        var c,
        d;
        d = j("form", {
            method: "post",
            action: a,
            enctype: "multipart/form-data"
        },
        {
            display: "none"
        },
        i.body);

 

注意代码一 url :http://export.highcharts.com/  和 代码二

由此,我们可以看出, Highcharts  的导出 js 是通过后台生产的图片;

 

 

验证:



 

 

 

结论: Highcharts 的导出 js 是通过模拟html请求,发送 SVG 到后台生成的图片

 

测试实现:

 

Svg转PNG的工具类:

  

package com.topinfo.qyaqsc.common;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.PNGTranscoder;

/**
 *@Description: 将svg转换为png格式的图片
 *@Author:杨攀
 *@Since:2013-11-4下午01:36:30
 */
public class SvgPngConverter {
 
    /**
     *@Description: 将svg字符串转换为png
     *@Author:杨攀
     *@Since: 2013-11-4下午01:36:54
     *@param svgCode svg代码
     *@param pngFilePath  保存的路径
     *@throws IOException io异常
     *@throws TranscoderException svg代码异常
     */
    public static void convertToPng(String svgCode,String pngFilePath) throws IOException,TranscoderException{

        File file = new File (pngFilePath);

        FileOutputStream outputStream = null;
        try {
            file.createNewFile ();
            outputStream = new FileOutputStream (file);
            convertToPng (svgCode, outputStream);
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close ();
                } catch (IOException e) {
                    e.printStackTrace ();
                }
            }
        }
    }

    /**
     *@Description: 将svgCode转换成png文件,直接输出到流中
     *@Author:杨攀
     *@Since: 2013-11-4下午01:37:56
     *@param svgCode svg代码
     *@param outputStream 输出流
     *@throws TranscoderException 异常
     *@throws IOException io异常
     */
    public static void convertToPng(String svgCode,OutputStream outputStream) throws TranscoderException,IOException{
        try {
            byte[] bytes = svgCode.getBytes ("UTF-8");
            PNGTranscoder t = new PNGTranscoder ();
            TranscoderInput input = new TranscoderInput (new ByteArrayInputStream (bytes));
            TranscoderOutput output = new TranscoderOutput (outputStream);
            t.transcode (input, output);
            outputStream.flush ();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close ();
                } catch (IOException e) {
                    e.printStackTrace ();
                }
            }
        }
    }
}

   

   测试工具类:

    public static void main(String[] args) throws Exception{
        
        String svg = "<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns=\"http://www.w3.org/2000/svg\" width=\"600\" height=\"400\" version=\"1.1\"><desc>Created with Highcharts 3.0.7</desc><defs><clipPath id=\"highcharts-7\"><rect fill=\"none\" x=\"1\" y=\"0\" width=\"288\" height=\"513\" /></clipPath></defs><rect fill=\"#ffffff\" x=\"0\" y=\"0\" width=\"600\" height=\"400\" rx=\"0\" ry=\"0\" /><g class=\"highcharts-grid\"  /><g class=\"highcharts-grid\" ><path opacity=\"1\" fill=\"none\" stroke=\"#c0c0c0\" stroke-width=\"1\" d=\"M 123.5 59 L 123.5 348\"  /><path opacity=\"1\" fill=\"none\" stroke=\"#c0c0c0\" stroke-width=\"1\" d=\"M 169.5 59 L 169.5 348\"  /><path opacity=\"1\" fill=\"none\" stroke=\"#c0c0c0\" stroke-width=\"1\" d=\"M 216.5 59 L 216.5 348\"  /><path opacity=\"1\" fill=\"none\" stroke=\"#c0c0c0\" stroke-width=\"1\" d=\"M 263.5 59 L 263.5 348\"  /><path opacity=\"1\" fill=\"none\" stroke=\"#c0c0c0\" stroke-width=\"1\" d=\"M 309.5 59 L 309.5 348\"  /><path opacity=\"1\" fill=\"none\" stroke=\"#c0c0c0\" stroke-width=\"1\" d=\"M 356.5 59 L 356.5 348\"  /><path opacity=\"1\" fill=\"none\" stroke=\"#c0c0c0\" stroke-width=\"1\" d=\"M 402.5 59 L 402.5 348\"  /><path opacity=\"1\" fill=\"none\" stroke=\"#c0c0c0\" stroke-width=\"1\" d=\"M 449.5 59 L 449.5 348\"  /><path opacity=\"1\" fill=\"none\" stroke=\"#c0c0c0\" stroke-width=\"1\" d=\"M 496.5 59 L 496.5 348\"  /><path opacity=\"1\" fill=\"none\" stroke=\"#c0c0c0\" stroke-width=\"1\" d=\"M 542.5 59 L 542.5 348\"  /><path opacity=\"1\" fill=\"none\" stroke=\"#c0c0c0\" stroke-width=\"1\" d=\"M 590.5 59 L 590.5 348\"  /><path opacity=\"1\" fill=\"none\" stroke=\"#c0c0c0\" stroke-width=\"1\" d=\"M 76.5 59 L 76.5 348\"  /></g><g class=\"highcharts-axis\" ><path opacity=\"1\" fill=\"none\" stroke=\"#c0d0e0\" stroke-width=\"1\" d=\"M 77 260.5 L 72 260.5\" /><path opacity=\"1\" fill=\"none\" stroke=\"#c0d0e0\" stroke-width=\"1\" d=\"M 77 175.5 L 72 175.5\" /><path opacity=\"1\" fill=\"none\" stroke=\"#c0d0e0\" stroke-width=\"1\" d=\"M 77 90.5 L 72 90.5\" /><path opacity=\"1\" fill=\"none\" stroke=\"#c0d0e0\" stroke-width=\"1\" d=\"M 77 345.5 L 72 345.5\" /><text visibility=\"visible\" style=\"color: rgb(77, 117, 158); font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 12px; font-weight: bold; fill: #4d759e;\" text-anchor=\"middle\" transform=\"translate(0) rotate(270 28.38 203.5)\" x=\"28.38\" y=\"203.5\" ><tspan x=\"28.38\">Altitude</tspan></text><path visibility=\"visible\" fill=\"none\" stroke=\"#c0d0e0\" stroke-width=\"1\" d=\"M 76.5 59 L 76.5 348\"  /></g><g class=\"highcharts-axis\" ><text visibility=\"visible\" style=\"color: rgb(77, 117, 158); font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 12px; font-weight: bold; fill: #4d759e;\" text-anchor=\"middle\" transform=\"translate(0)\" x=\"333.5\" y=\"379\" ><tspan x=\"333.5\">Temperature</tspan></text><path visibility=\"visible\" fill=\"none\" stroke=\"#c0d0e0\" stroke-width=\"2\" d=\"M 77 348 L 590 348\"  /></g><g class=\"highcharts-series-group\" ><g class=\"highcharts-series\" visibility=\"visible\" clip-path=\"url(#highcharts-7)\" transform=\"translate(590 348) rotate(90) scale(-1 1) scale(1)\"  width=\"513\" height=\"289\"><path fill=\"none\" stroke=\"#2f7ed8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M 2.72642 23.3182 C 2.72642 23.3182 23.1745 296.141 36.8066 326.455 C 50.4387 356.768 57.2547 356.768 70.8868 356.768 C 84.5189 356.768 91.3349 342.218 104.967 310.132 C 118.599 278.046 125.415 237.379 139.047 196.339 C 152.679 155.299 159.495 104.932 173.127 104.932 C 186.759 104.932 193.575 172.834 207.208 222.455 C 220.84 272.077 227.656 307.52 241.288 353.037 C 254.92 398.554 275.368 450.041 275.368 450.041\"  /><path class=\" highcharts-tracker\" visibility=\"visible\" fill=\"none\" stroke=\"rgb(192, 192, 192)\" stroke-linejoin=\"round\" stroke-opacity=\"0.0001\" stroke-width=\"22\" d=\"M -7.27358 23.3182 L 2.72642 23.3182 C 2.72642 23.3182 23.1745 296.141 36.8066 326.455 C 50.4387 356.768 57.2547 356.768 70.8868 356.768 C 84.5189 356.768 91.3349 342.218 104.967 310.132 C 118.599 278.046 125.415 237.379 139.047 196.339 C 152.679 155.299 159.495 104.932 173.127 104.932 C 186.759 104.932 193.575 172.834 207.208 222.455 C 220.84 272.077 227.656 307.52 241.288 353.037 C 254.92 398.554 275.368 450.041 275.368 450.041 L 285.368 450.041\"  /></g><g class=\"highcharts-markers highcharts-tracker\" visibility=\"visible\" clip-path=\"none\" transform=\"translate(590 348) rotate(90) scale(-1 1) scale(1)\"  width=\"513\" height=\"289\"><path fill=\"#2f7ed8\" d=\"M 275 446.041 C 280.328 446.041 280.328 454.041 275 454.041 C 269.672 454.041 269.672 446.041 275 446.041 Z\" /><path fill=\"#2f7ed8\" d=\"M 241 349.037 C 246.328 349.037 246.328 357.037 241 357.037 C 235.672 357.037 235.672 349.037 241 349.037 Z\" /><path fill=\"#2f7ed8\" d=\"M 207 218.455 C 212.328 218.455 212.328 226.455 207 226.455 C 201.672 226.455 201.672 218.455 207 218.455 Z\" /><path fill=\"#2f7ed8\" d=\"M 173 100.932 C 178.328 100.932 178.328 108.932 173 108.932 C 167.672 108.932 167.672 100.932 173 100.932 Z\" /><path fill=\"#2f7ed8\" d=\"M 139 192.339 C 144.328 192.339 144.328 200.339 139 200.339 C 133.672 200.339 133.672 192.339 139 192.339 Z\" /><path fill=\"#2f7ed8\" d=\"M 104 306.132 C 109.328 306.132 109.328 314.132 104 314.132 C 98.672 314.132 98.672 306.132 104 306.132 Z\" /><path fill=\"#2f7ed8\" d=\"M 70 352.768 C 75.328 352.768 75.328 360.768 70 360.768 C 64.672 360.768 64.672 352.768 70 352.768 Z\" /><path fill=\"#2f7ed8\" d=\"M 36 322.455 C 41.328 322.455 41.328 330.455 36 330.455 C 30.672 330.455 30.672 322.455 36 322.455 Z\" /><path fill=\"#2f7ed8\" d=\"M 2 19.3182 C 7.328 19.3182 7.328 27.3182 2 27.3182 C -3.328 27.3182 -3.328 19.3182 2 19.3182 Z\" /></g></g><text class=\"highcharts-title\" style=\"color: rgb(39, 75, 109); font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 16px; fill: #274b6d;\" text-anchor=\"middle\" x=\"300\" y=\"25\" ><tspan x=\"300\">Atmosphere Temperature by Altitude</tspan></text><text class=\"highcharts-subtitle\" style=\"color: rgb(77, 117, 158); font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 12px; fill: #4d759e;\" text-anchor=\"middle\" x=\"300\" y=\"40\" ><tspan x=\"300\">According to the Standard Atmosphere Model</tspan></text><g class=\"highcharts-axis-labels\" ><text style=\"color: rgb(102, 102, 102); line-height: 14px; font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 11px; cursor: default; fill: #666;\" opacity=\"1\" text-anchor=\"end\" x=\"69\" y=\"350.2736\"><tspan x=\"69\">0km</tspan></text><text style=\"color: rgb(102, 102, 102); line-height: 14px; font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 11px; cursor: default; fill: #666;\" opacity=\"1\" text-anchor=\"end\" x=\"69\" y=\"265.0731\"><tspan x=\"69\">25km</tspan></text><text style=\"color: rgb(102, 102, 102); line-height: 14px; font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 11px; cursor: default; fill: #666;\" opacity=\"1\" text-anchor=\"end\" x=\"69\" y=\"179.8726\"><tspan x=\"69\">50km</tspan></text><text style=\"color: rgb(102, 102, 102); line-height: 14px; font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 11px; cursor: default; fill: #666;\" opacity=\"1\" text-anchor=\"end\" x=\"69\" y=\"94.6722\"><tspan x=\"69\">75km</tspan></text></g><g class=\"highcharts-axis-labels\" ><text style=\"color: rgb(102, 102, 102); line-height: 14px; font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 11px; cursor: default; fill: #666;\" opacity=\"1\" text-anchor=\"middle\" x=\"77\" y=\"362\"><tspan x=\"77\">-90掳</tspan></text><text style=\"color: rgb(102, 102, 102); line-height: 14px; font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 11px; cursor: default; fill: #666;\" opacity=\"1\" text-anchor=\"middle\" x=\"123.6364\" y=\"362\"><tspan x=\"123.6364\">-80掳</tspan></text><text style=\"color: rgb(102, 102, 102); line-height: 14px; font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 11px; cursor: default; fill: #666;\" opacity=\"1\" text-anchor=\"middle\" x=\"170.2727\" y=\"362\"><tspan x=\"170.2727\">-70掳</tspan></text><text style=\"color: rgb(102, 102, 102); line-height: 14px; font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 11px; cursor: default; fill: #666;\" opacity=\"1\" text-anchor=\"middle\" x=\"216.9091\" y=\"362\"><tspan x=\"216.9091\">-60掳</tspan></text><text style=\"color: rgb(102, 102, 102); line-height: 14px; font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 11px; cursor: default; fill: #666;\" opacity=\"1\" text-anchor=\"middle\" x=\"263.5455\" y=\"362\"><tspan x=\"263.5455\">-50掳</tspan></text><text style=\"color: rgb(102, 102, 102); line-height: 14px; font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 11px; cursor: default; fill: #666;\" opacity=\"1\" text-anchor=\"middle\" x=\"310.1818\" y=\"362\"><tspan x=\"310.1818\">-40掳</tspan></text><text style=\"color: rgb(102, 102, 102); line-height: 14px; font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 11px; cursor: default; fill: #666;\" opacity=\"1\" text-anchor=\"middle\" x=\"356.8182\" y=\"362\"><tspan x=\"356.8182\">-30掳</tspan></text><text style=\"color: rgb(102, 102, 102); line-height: 14px; font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 11px; cursor: default; fill: #666;\" opacity=\"1\" text-anchor=\"middle\" x=\"403.4546\" y=\"362\"><tspan x=\"403.4546\">-20掳</tspan></text><text style=\"color: rgb(102, 102, 102); line-height: 14px; font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 11px; cursor: default; fill: #666;\" opacity=\"1\" text-anchor=\"middle\" x=\"450.0909\" y=\"362\"><tspan x=\"450.0909\">-10掳</tspan></text><text style=\"color: rgb(102, 102, 102); line-height: 14px; font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 11px; cursor: default; fill: #666;\" opacity=\"1\" text-anchor=\"middle\" x=\"496.7273\" y=\"362\"><tspan x=\"496.7273\">0掳</tspan></text><text style=\"color: rgb(102, 102, 102); line-height: 14px; font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 11px; cursor: default; fill: #666;\" opacity=\"1\" text-anchor=\"middle\" x=\"543.3637\" y=\"362\"><tspan x=\"543.3637\">10掳</tspan></text><text style=\"color: rgb(102, 102, 102); line-height: 14px; font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 11px; cursor: default; fill: #666;\" opacity=\"1\" text-anchor=\"middle\" x=\"590\" y=\"362\"><tspan x=\"590\">20掳</tspan></text></g><g class=\"highcharts-tooltip\" style=\"padding: 0px; white-space: nowrap; cursor: default;\" transform=\"translate(0 -999)\" ><rect fill=\"none\" fill-opacity=\"0.85\" stroke=\"black\" stroke-opacity=\"0.05\" stroke-width=\"5\" transform=\"translate(1 1)\" x=\"0.5\" y=\"0.5\" width=\"16\" height=\"16\" rx=\"3\" ry=\"3\"  /><rect fill=\"none\" fill-opacity=\"0.85\" stroke=\"black\" stroke-opacity=\"0.1\" stroke-width=\"3\" transform=\"translate(1 1)\" x=\"0.5\" y=\"0.5\" width=\"16\" height=\"16\" rx=\"3\" ry=\"3\"  /><rect fill=\"none\" fill-opacity=\"0.85\" stroke=\"black\" stroke-opacity=\"0.15\" stroke-width=\"1\" transform=\"translate(1 1)\" x=\"0.5\" y=\"0.5\" width=\"16\" height=\"16\" rx=\"3\" ry=\"3\"  /><rect fill=\"rgb(255, 255, 255)\" fill-opacity=\"0.85\" x=\"0.5\" y=\"0.5\" width=\"16\" height=\"16\" rx=\"3\" ry=\"3\" /><text style=\"color: rgb(51, 51, 51); font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 12px; fill: #333333;\" x=\"8\" y=\"21\"  /></g><text style=\"color: rgb(144, 144, 144); font-family: 'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif; font-size: 9px; cursor: pointer; fill: #909090;\" text-anchor=\"end\" x=\"590\" y=\"395\" ><tspan x=\"590\">Highcharts.com</tspan></text></svg>";
        
        SvgPngConverter.convertToPng (svg, "E:\\xxx.png");
         
    }

 经过测试,成功的将 SVG 转换为 图片;

 

自己实现:

1、修改代码一片段的 url:为我们自己的 action

2、在action方法中,把svg转成图片

   

    private String filename;
    
    private String type;
    
    private String width;
    
    private String scale;
    
    private String svg;

    //省略 get set 方法

 

 

    /**
     *@Description: 分析报告 导出
     *@Author:杨攀
     *@Since: 2013-11-4下午02:59:37
     *@return
     */
    public String exportWord(){
         
        HttpServletResponse response = ServletActionContext.getResponse ();
        HttpServletRequest request = ServletActionContext.getRequest ();
        ServletOutputStream outputStream = null;
        try {
            // 设置字符集
            request.setCharacterEncoding ("UTF-8"); 
            // html输出 键 值 Content-Type image/png;charset=utf-8
            response.setContentType ("image/png;charset=UTF-8"); 
            //键 值  Content-Disposition attachment; filename=chart.png
            response.addHeader ("Content-Disposition", "attachment; filename=\"" + filename + ".png\""); 
            response.setCharacterEncoding ("UTF-8");
            outputStream =  response.getOutputStream ();
            
            if(StringUtils.isNotBlank (svg)){
                SvgPngConverter.convertToPng (svg, outputStream);
            }
            
        } catch (Exception e) { 
            
        }
        return null;
    }

 

经过测试,成功的将 SVG 转换为 图片,

 

那么剩下来就简单了,只需要把图片插入 word 模板 即可。

 

 

回顾:

 

一开始写的Svg转换图片测试有问题,后面经过google查询才解决问题:

网址:https://issues.apache.org/bugzilla/show_bug.cgi?id=44682
我开始百度,一直没解决,后面改成google,立刻就发现了问题所在。还是 google 给力

原来是 maven  依赖错误导致的。


最后:使用这个方法需要引用batic相关的包,maven pom文件如下:

 

		<!-- svg 生产 图片 -->
		<dependency>
			<groupId>org.apache.xmlgraphics</groupId>
			<artifactId>batik-codec</artifactId>
			<version>1.7</version>
		</dependency>

 

 

 

第一步好了, 顺利解决! O(∩_∩)O哈哈~.............................

 

导出到 word  的原理总结:
1、通过 Highcharts 的 getSvg() 方法获取到 每个图表的 svg 等参数放到隐藏域

2、提交到后台,根据svg生产图片输出到 word 中

 

补充:

Highcharts API:

http://api.highcharts.com/highcharts#Chart

 

根据API 中可以找到 getSvg() 方法

 

 

获取svg的方法示例:

$('#button').click(function() {
        var chart = $('#container').highcharts()
            svg = chart.getSVG()
                .replace(/</g, '\n&lt;') // make it slightly more readable
                .replace(/>/g, '&gt;');

        document.body.innerHTML = '<pre>'+ svg +'</pre>';
    });

  

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值