在项目中用到了amcharts,amcharts图标统计插件是利用SVG实现的,其自带下载png功能,但是不支持IE以下浏览器。因此研究了SVG转换为png,最终实现的效果是将amcharts生成一张png写入一个excel并提供下载。
1.SVG简介:
SVG 意为可缩放矢量图形(Scalable Vector Graphics)。说白了就是利用xml定义图形。
SVG 使用 XML 格式定义图像。
例如一个简单的圆形:
<html> <body> <h1>My first SVG</h1> <svg xmlns="http://www.w3.org/2000/svg" version="1.1"> <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" /> </svg> </body> </html>
结果:
注意:如果将SVG的父标签去掉也是正常使用的,比如:(用浏览器打开后缀为下面后缀为SVG的文件)
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"> <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" /> </svg>
结果:
但是如果将SVG根标签的xmlns属性去掉是不会显示为图形的,比如:
<svg version="1.1"> <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" /> </svg>
总结:SVG如果正常显示为图形,需要在SVG根标签引入 xmlns="http://www.w3.org/2000/svg"
更多的关于SVG的使用参考菜鸟教程:http://www.runoob.com/svg/svg-tutorial.html
2.SVG转换为PNG
会研究前台JS生成和后台利用batik生成png。所有用到的JS以及lib或者其他会在最后提供github连接。
2.1前台转换(不支持IE)
需要的JS:saveSvgAsPng.js ,前台下载也比较简单。支持chrome、firefox等主流浏览器(Ie就不主流了。。。。。)
简单的测试:
<html> <body> <h1>My first SVG</h1> <div> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="testSvg"> <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" /> </svg> </div> <button onclick="downloadSvg()">download</button> </body> <script src="saveSvgAsPng.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> function downloadSvg(){ //下载的方法--第一个参数是SVG的顶级元素,第二个参数是文件名字 saveSvgAsPng(document.getElementById("testSvg"), "diagram.png"); } </script> </html>
2.2后台将SVG转换为PNG
后台转换也就是将SVGCODE转换为PNG,注意SVGCODE是需要xmlns属性的,否则会转换失败:
1.依赖的jar包:(commons-io包是为了读取svgcode)
2.工程结构
3. 需要转换的SVGCODE:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"> <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" /> </svg>
直接浏览器打开效果:
4.转换的代码以及测试:
package cn.qlq.svg2png; 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.ImageTranscoder; import org.apache.batik.transcoder.image.PNGTranscoder; import org.apache.commons.io.FileUtils; /** * 将svg转换为png格式的图片 * * */ public abstract class SVG2PNGUtils { /** * 将svg字符串转换为png * * @param svgCode * svg代码 * @param pngFilePath * 保存的路径 * @throws TranscoderException * svg代码异常 * @throws IOException * io错误 */ 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(); } } } } /** * 将svgCode转换成png文件,直接输出到流中 * * @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); // 增加图片的属性设置(单位是像素)---下面是写死了,实际应该是根据SVG的大小动态设置,默认宽高都是400 t.addTranscodingHint(ImageTranscoder.KEY_WIDTH, new Float(941)); t.addTranscodingHint(ImageTranscoder.KEY_HEIGHT, new Float(800)); 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 IOException, TranscoderException { ClassLoader classLoader = SVG2PNGUtils.class.getClassLoader(); String filePath = classLoader.getResource("cn/qlq/svg2png/svgtest.svg").getPath(); String svgCode = FileUtils.readFileToString(new File(filePath), "UTF-8"); convertToPng(svgCode, "e:/test.png"); } }
结果会生成PNG。(再次强调SVG文件的xmlns一定要写)
至此就实现了SVG转换为PNG,在web应用中我们可以将SVGCODE传到后台处理之后生成一个PNG并提供下载,再深入一点可以将图片再写入excel中提供下载。
原文地址:https://www.cnblogs.com/qlqwjy/p/9780021.html