java生成svg_java生成饼图svg及JFreeChart生成svg图表

本文介绍了如何使用Java生成SVG饼图,包括带有标签的2D饼图和3D饼图。通过 Batik 工具,可以将JFreeChart的图表转换为SVG格式。文章提供了详细的代码示例,展示了如何创建和保存SVG文件,并提到了查看SVG时可能出现的中文乱码问题。
摘要由CSDN通过智能技术生成

Jfreechart本身不能生成SVG图形,但是可以借助另外一个东西,辅助生成.好像是这个:batik ,具体代码请看下文

一:Java生成svg饼图,附带了一个标签显示各个颜色代表的部分

package com.tellhow.svg;

import java.io.File;

import java.io.FileOutputStream;

/**

*

* @author 风絮NO.1

*

*/

public class CakySvgWithLabel {

//定义不同的颜色

static String[] colors ={"#f2e692", "#aa1111",

"#799AE1", "#3e941b",

"#66cc00", "#297110",

"#d6a97b", "#82522b",

"#aaaaff", "#1111aa",

"#ff2222", "#ffaaaa"};

static String initialize(double [] percents,String[]names){

StringBuffer sfile = new StringBuffer();

sfile.append("<?xml version='1.0' encoding='UTF-8'?>");

sfile.append("\n");

sfile.append("

sfile.append("\n");

sfile.append("xmlns='http://www.w3.org/2000/svg'");

sfile.append("\n");

sfile.append("xmlns:xlink='http://www.w3.org/1999/xlink'");

sfile.append("\n");

sfile.append("xml:space='default'");

sfile.append("\n");

sfile.append("version='1.1' width='100%' height='100%' viewBox='0 0 2024 570'>");

sfile.append("\n");

sfile.append("");

sfile.append("\n");

sfile.append("");

sfile.append("\n");

//循环创造path标签.

String path =creatPath(502, 300, 300, percents,names);//中心点式503,300.

sfile.append(path);

sfile.append("");

sfile.append("\n");

sfile.append("

");

return sfile.toString();

}

/**

*

* @param x0 中心点横坐标

* @param y0 中心点纵坐标

* @param r 半径

* @param percents 百分比数组

* @param names 显示颜色代表的名称

* @return

*/

public static String creatPath(double x0,double y0,double r,double[]percents,String[]names){

StringBuffer sfile =new StringBuffer();

double x1=0; //新扇形的x坐标

double y1=0; //新扇形的y坐标

double middleX=0; //文本显示的坐标,包括竖线显示的坐标

double middleY=0;

double radian =0; //弧度

double textRadian=0; //文本显示位置度弧度

double k=0;

int N=10;

for(int i=0;i

if(i==0){

radian =getRadian(percents[0]);

textRadian=radian/2;

x1 = (x0+getCos(radian)*r);

y1 = (y0-getSin(radian)*r);

middleX=(x0+getCos(textRadian)*r);

middleY=(y0-getSin(textRadian)*r);

double percent = Math.round(percents[0]*100)/100.0;//获得精确到两位小数点的坐标.

k=Math.abs((middleY-y0)/(middleX-x0));//获得扇形终点的坐标,与中心点连成的直线的斜率.(取正值)

double sita= Math.atan(k);//求斜角

double lineLen=50;

double textLen=70;

if(radian<6){

lineLen=90;

textLen=110;//控制指示线的长度,与文字的位置

}

if(percents[i]!=0){//当一个类型为0时,饼图展示

if((textRadian

sfile.append("");

sfile.append("\n");

sfile.append(""+percent+"%");

}else if ((textRadian>(Math.PI/2)&&textRadian

sfile.append("");

sfile.append("\n");

sfile.append(""+percent+"%");

}else if ((textRadian>(Math.PI)&&textRadian

sfile.append("");

sfile.append("\n");

sfile.append(""+percent+"%");

}else if((textRadian>(Math.PI*3/2)&&textRadian

sfile.append("");

sfile.append("\n");

sfile.append(""+percent+"%");

}

sfile.append("\n");

if(getRadian(percents[0])>Math.PI){

sfile.append("");

}else{

sfile.append("");

}

sfile.append("\n");

}

sfile.append("");

sfile.append("\n");

sfile.append(""+names[0]+"");

sfile.append("\n");

}else{

textRadian = radian+(getRadian(percents[i])/2);//获取指示线与X轴的弧度.

radian =radian+getRadian(percents[i]);//第i个扇形前面的弧度的总和

middleX=(x0+getCos(textRadian)*r);

middleY=(y0-getSin(textRadian)*r);

double percent = Math.round(percents[i]*100)/100.0;

k=Math.abs((middleY-y0)/(middleX-x0));

double lineLen=50;

double textLen=70;

if(radian<6){

lineLen=90;

textLen=110;

}

double sita= Math.atan(k);

if(percents[i]!=0){//当一个类型为0时,饼图展示

if((textRadian

sfile.append("");

sfile.append("\n");

sfile.append(""+percent+"%");

}else if ((textRadian>(Math.PI/2)&&textRadian

sfile.append("");

sfile.append("\n");

sfile.append(""+percent+"%");

}else if ((textRadian>(Math.PI)&&textRadian

sfile.append("");

sfile.append("\n");

sfile.append(""+percent+"%");

}else if((textRadian>(Math.PI*3/2)&&textRadian

sfile.append("");

sfile.append("\n");

sfile.append(""+percent+"%");

}

sfile.append("\n");

// 参数 1 表示 画大于180的弧, 0 表示画小于180的弧 (这个地方比较重要)

if(getRadian(percents[i])>Math.PI){

sfile.append("");

}else{

sfile.append("");

}

sfile.append("\n");

}

N+=50;

sfile.append("");

sfile.append("\n");

sfile.append(""+names[i]+"");

sfile.append("\n");

}

}

return sfile.toString();

}

//返回弧度

public static double getRadian(double fenshu){

return (fenshu*Math.PI)/50;

}

//返回正弦

public static double getSin(double radian){

return Math.sin(radian);

}

//返回余弦

public static double getCos(double radian){

return Math.cos(radian);

}

public static void main(String[] args) {

int[] data= {3,64,0,284,10};

String[] names={"主变:"+data[0]+"个","断路器:"+data[1]+"个","线路:"+data[2]+"个","刀闸:"+data[3]+"个","母线:"+data[4]+"个"};

create(data,names);

}

private static void create(int[] data,String[] names) {

try {

createSVG("d:/a.svg",getPercent(data),names);

} catch (Exception e) {

e.printStackTrace();

}

}

private static double[] getPercent(int data[]){

double sum=0;

double percents[] = new double[data.length];

for(int i=0;i

sum+=data[i];

}

for(int i=0;i

percents[i] =(data[i]/sum)*100;

}

return percents;

}

public static void createSVG(String fileRealPath, double[] percents,String[] names) throws Exception {

String sFile = initialize(percents,names);

try {

byte[] byteFil = sFile.getBytes("UTF-8");

File svgFile = new File(fileRealPath);

if (svgFile.exists()) {

svgFile.delete();

}

FileOutputStream fos = new FileOutputStream(svgFile);

fos.write(byteFil);

fos.close();

} catch (Exception ex) {

System.out.print(ex.getMessage());

}

}

}

二.java生成SVG 3D饼图.

(这个可以生成图形,但是不完善,我没有再修改代码啦,因为觉得这个东西不值,用jfreechart可能更好.功能更强到,只是这几个程序,让我更加了解了svg这个东西,里面的一些标签都干什么用的.等等.) 3D的这个,生成的效果图,会有断层的效果,主要是出现在第一现象和第四象限,即如果第一象限或第四象限,有两个扇形的话,就会出现断层,可以用这个工具进行调整:SVGDeveloper. 用它打开svg图形,然后将断层的扇形的代码,重新倒序排列一下.

package com.xj.svg;

import java.io.File;

import java.io.FileOutputStream;

public class Caky3DSVG {

static String[] colors ={"#d6a97b",

"#22FF22", "#aaffaa", "#799AE1",

"#9aabEe", "#3e941b", "#f2e692",

"#66cc00", "#297110", "#d6a97b",

"#82522b", "#aaaaff", "#1111aa",

"#ff2222", "#ffaaaa", "#aa1111"

};

public static void main(String[] args) {

double data[] = {20,20,50};

try {

createSVG("f:/f.svg",getPercent(data));

} catch (Exception e) {

e.printStackTrace();

}

}

static String initialize(double [] percent){

double percents[] = {10,15,5,20,40,10};

StringBuffer sfile = new StringBuffer();

sfile.append("<?xml version='1.0' encoding='UTF-8'?>");

sfile.append("\n");

sfile.append("

sfile.append("\n");

sfile.append("xmlns='http://www.w3.org/2000/svg'");

sfile.append("\n");

sfile.append("xmlns:xlink='http://www.w3.org/1999/xlink'");

sfile.append("\n");

sfile.append("xml:space='default'");

sfile.append("\n");

sfile.append("version='1.1' width='100%' height='100%' viewBox='0 0 1024 600'>");

sfile.append("\n");

sfile.append("");

sfile.append("\n");

String path = createPath(502, 300,300, 150, percents);

sfile.append(path);

sfile.append("");

sfile.append("\n");

sfile.append("

");

return sfile.toString();

}

/**

*

* @param x0 原点 X

* @param y0 原点 Y

* @param langR

* @param shortR

* @param fenshu

* @return

*/

static String createPath(double x0,double y0,double langR,double shortR ,double percents[]){

StringBuffer sfile = new StringBuffer();

double xBottom =0;

double yBottom =0;

double xBottom1=0;

double yBottom1=0;

double radian =0;

sfile.append("");

sfile.append("\n");

for(int i=0;i

System.out.println("i:"+i);

radian =radian+getRadian(percents[i]);//第i个扇形到 第一个扇形,弧度的总和.

System.out.println("弧度2:"+radian);

if (i==0){

System.out.println("弧度1:"+radian);

if(radian==Math.PI/2){

xBottom = x0;//底面的x坐标

yBottom = y0-shortR;//底面的y坐标

}else if(radian==Math.PI*3/2){

xBottom = x0;//底面的x坐标

yBottom = y0+shortR;//底面的y坐标

} else{

double tanRadian = Math.abs(Math.tan(radian));

double sqValue=shortR*shortR+tanRadian*tanRadian*langR*langR;

if(radian

System.out.println("if1:"+radian);

xBottom = x0+(langR*shortR)/Math.sqrt(sqValue);//底面的x坐标

yBottom = y0-(tanRadian*langR*shortR)/Math.sqrt(sqValue);//底面的y坐标

}

else if (radian>Math.PI/2&&radian<=Math.PI){

System.out.println("if2:"+radian);

xBottom =x0-(langR*shortR)/Math.sqrt(sqValue);

yBottom =y0-(tanRadian*langR*shortR)/Math.sqrt(sqValue);

}else if (radian>Math.PI&&radian

System.out.println("if3:"+radian);

xBottom =x0-(langR*shortR)/Math.sqrt(sqValue);

yBottom =y0+(tanRadian*langR*shortR)/Math.sqrt(sqValue);

}else if (radian>Math.PI*3/2&&radian

System.out.println("if4:"+radian);

xBottom = x0+(langR*shortR)/Math.sqrt(sqValue);

yBottom = y0+(tanRadian*langR*shortR)/Math.sqrt(sqValue);

}

}

if(getRadian(percents[0])>Math.PI){//大于 PI 弧度,即百分比超过50%

sfile.append("");

sfile.append("\n");

sfile.append("");

sfile.append("\n");

sfile.append("");

sfile.append("\n");

sfile.append("");

sfile.append("\n");

sfile.append("");

sfile.append("\n");

}else{

sfile.append("");

sfile.append("\n");

sfile.append("");

sfile.append("\n");

sfile.append("");

sfile.append("\n");

sfile.append("");

sfile.append("\n");

sfile.append("");

sfile.append("\n");

}

}else{

if(radian==Math.PI/2){

xBottom1= x0;//底面的x坐标

yBottom1= y0-shortR;//底面的y坐标

}else if(radian==Math.PI*3/2){

xBottom1 = x0;//底面的x坐标

yBottom1 = y0+shortR;//底面的y坐标

} else{

double tanRadian = Math.abs(Math.tan(radian));

double sqValue=shortR*shortR+tanRadian*tanRadian*langR*langR;

if(radian

System.out.println("if1:"+radian);

xBottom1 = x0+(langR*shortR)/Math.sqrt(sqValue);//底面的x坐标

yBottom1 = y0-(tanRadian*langR*shortR)/Math.sqrt(sqValue);//底面的y坐标

}

else if (radian>Math.PI/2&&radian<=Math.PI){

System.out.println("if2:"+radian);

xBottom1 =x0-(langR*shortR)/Math.sqrt(sqValue);

yBottom1 =y0-(tanRadian*langR*shortR)/Math.sqrt(sqValue);

}else if (radian>Math.PI&&radian

System.out.println("if3:"+radian);

xBottom1 =x0-(langR*shortR)/Math.sqrt(sqValue);

yBottom1 =y0+(tanRadian*langR*shortR)/Math.sqrt(sqValue);

}else if (radian>Math.PI*3/2){

System.out.println("if4:"+radian);

xBottom1 = x0+(langR*shortR)/Math.sqrt(sqValue);

yBottom1 = y0+(tanRadian*langR*shortR)/Math.sqrt(sqValue);

}

}

if(getRadian(percents[i])>Math.PI){//大于 PI 弧度,即百分比超过50%

System.out.println("大于pi");

sfile.append("");

sfile.append("\n");

sfile.append("");

sfile.append("\n");

sfile.append("");

sfile.append("\n");

sfile.append("");

sfile.append("\n");

sfile.append("");

sfile.append("\n");

}else{

System.out.println("小于pi");

sfile.append("");

sfile.append("\n");

sfile.append("");

sfile.append("\n");

sfile.append("");

sfile.append("\n");

sfile.append("");

sfile.append("\n");

sfile.append("");

sfile.append("\n");

}

xBottom=xBottom1;

yBottom=yBottom1;

}

}

return sfile.toString();

}

//返回弧度

public static double getRadian(double percent){

return (percent*Math.PI)/50;

}

//返回正弦

public static double getSin(double radian){

return Math.sin(radian);

}

//返回余弦

public static double getCos(double radian){

return Math.cos(radian);

}

private static double[] getPercent(double data[]){

double sum=0;

double percents[] = new double[data.length];

for(int i=0;i

sum+=data[i];

}

for(int i=0;i

percents[i] =(data[i]/sum)*100;

}

return percents;

}

public static void createSVG(String fileRealPath, double[] percents) throws Exception {

String sFile = initialize(percents);

try {

byte[] byteFil = sFile.getBytes("UTF-8");

File svgFile = new File(fileRealPath);

if (svgFile.exists()) {

svgFile.delete();

}

FileOutputStream fos = new FileOutputStream(svgFile);

fos.write(byteFil);

fos.close();

} catch (Exception ex) {

System.out.print(ex.getMessage());

}

}

}

三.使用Jfreechart动态生成svg图形:

import java.awt.Rectangle;

import java.io.*;

import org.jfree.chart.*;

import org.apache.batik.dom.GenericDOMImplementation;

import org.apache.batik.svggen.SVGGraphics2D;

import org.jfree.data.category.CategoryDataset;

import org.jfree.data.category.DefaultCategoryDataset;

import org.jfree.chart.plot.*;

import org.w3c.dom.DOMImplementation;

import org.w3c.dom.Document;

/**

* 该类用于演示最简单的柱状图生成

*/

public class BarChartDemo {

public static void main(String[] args) throws IOException {

CategoryDataset dataset = getDataSet();

// 创建JFreeChart对象,在内存中间创建出对应的图像

JFreeChart chart = ChartFactory.createBarChart3D("水果产量图", // 图表标题

"水果", // 目录轴的显示标签

"产量", // 数值轴的显示标签

dataset, // 数据集

PlotOrientation.VERTICAL, // 图表方向:水平、垂直

true, // 是否显示图例(对于简单的柱状图必须是false)

false, // 是否生成工具

false // 是否生成URL链接

);

File fo_svg = new File("D:\\fruit3.svg");

Rectangle bounds = new Rectangle(0,0,400,300);

exportChartAsSVG(chart,bounds,fo_svg);

}

private static void exportChartAsJPG() throws FileNotFoundException, IOException {

// 得到数据Dataset

CategoryDataset dataset = getDataSet();

// 创建JFreeChart对象,在内存中间创建出对应的图像

JFreeChart chart = ChartFactory.createBarChart3D("水果产量图", // 图表标题

"水果", // 目录轴的显示标签

"产量", // 数值轴的显示标签

dataset, // 数据集

PlotOrientation.VERTICAL, // 图表方向:水平、垂直

true, // 是否显示图例(对于简单的柱状图必须是false)

false, // 是否生成工具

false // 是否生成URL链接

);

FileOutputStream fos_jpg = null;

try {

fos_jpg = new FileOutputStream("D:/fruit3.jpg");

ChartUtilities.writeChartAsJPEG(fos_jpg, 1, chart, 400, 300, null);

} finally {

try {

fos_jpg.close();

} catch (Exception e) {

}

}

}

/**

* 获取一个演示用的简单数据集对象

*

* @return

*/

private static CategoryDataset getDataSet() {

DefaultCategoryDataset dataset = new DefaultCategoryDataset();

dataset.addValue(100, "1", "葡萄");

dataset.addValue(200, "1", "梨子");

dataset.addValue(200, "1", "荔枝");

dataset.addValue(300, "2", "葡萄");

dataset.addValue(400, "2", "梨子");

dataset.addValue(500, "2", "荔枝");

return dataset;

}

/**

* 获取一个演示用的组合数据集对象

*

* @return

*/

private static CategoryDataset getDataSet2() {

DefaultCategoryDataset dataset = new DefaultCategoryDataset();

dataset.addValue(100, "北京", "苹果");

dataset.addValue(100, "上海", "苹果");

dataset.addValue(100, "广州", "苹果");

dataset.addValue(200, "北京", "梨子");

dataset.addValue(200, "上海", "梨子");

dataset.addValue(200, "广州", "梨子");

dataset.addValue(300, "北京", "葡萄");

dataset.addValue(300, "上海", "葡萄");

dataset.addValue(300, "广州", "葡萄");

dataset.addValue(400, "北京", "香蕉");

dataset.addValue(400, "上海", "香蕉");

dataset.addValue(400, "广州", "香蕉");

dataset.addValue(500, "北京", "荔枝");

dataset.addValue(500, "上海", "荔枝");

dataset.addValue(500, "广州", "荔枝");

return dataset;

}

/**

* Exports a JFreeChart to a SVG file.

*

* @param chart JFreeChart to export

* @param bounds the dimensions of the viewport

* @param svgFile the output file.

* @throws IOException if writing the svgFile fails.

*/

private static void exportChartAsSVG(JFreeChart chart, Rectangle bounds, File svgFile) throws IOException {

// Get a DOMImplementation and create an XML document

DOMImplementation domImpl =

GenericDOMImplementation.getDOMImplementation();

Document document = domImpl.createDocument(null, "svg", null);

// Create an instance of the SVG Generator

SVGGraphics2D svgGenerator = new SVGGraphics2D(document);

// draw the chart in the SVG generator

chart.draw(svgGenerator, bounds);

// Write svg file

OutputStream outputStream = new FileOutputStream(svgFile);

Writer out = new OutputStreamWriter(outputStream, "UTF-8");

svgGenerator.stream(out, true /* use css */);

outputStream.flush();

outputStream.close();

}

}

用这个的时候需要注意两点:

1 .jfreechart本身不能生成svg图形,需要用到batik .一个java工具包,apache的.

batik-awt-util.jar

batik-dom.jar

batik-svggen.jar

batik-util.jar

batik-xml.jar

jfreechart-1.0.0.jar

2.就是可能生成svg,当你查看的时候不支持中文. 我记得好像是如果是安装的adobe的那个查看器,在IE里面浏览的话好像是中文乱码,如果用另外一个叫做 Renesis SVG Player ,这个查看器就是支持中文的.

以上内容就是java生成饼图svg及JFreeChart生成svg图表的全部内容,希望大家喜欢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值