服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服务器之家 - 编程语言 - JAVA教程 - java生成饼图svg及JFreeChart生成svg图表

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

2020-01-02 14:44jhmyuan JAVA教程

java生成饼图svg,代码实现感觉有点复杂,个人认为不如用JFreeChart,这篇文章主要介绍java生成饼图svg及JFreeChart生成svg图表,有需要的小伙伴可以参考下

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
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("<svg xmlns:svg='http://www.w3.org/2000/svg'");
 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("<defs></defs>");
  sfile.append("\n");
  sfile.append("<g stroke-width='1' stroke='#FFFFFF' transform='matrix(1,0,0,1,16.384,-9.83)' xmlns='http://www.w3.org/2000/svg'>");
  sfile.append("\n");
  //循环创造path标签.
  String path =creatPath(502, 300, 300, percents,names);//中心点式503,300.
  sfile.append(path);
  sfile.append("</g>");
  sfile.append("\n");
  sfile.append("</svg>");
 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<percents.length;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<(Math.PI/2))){
    sfile.append("<line x1='"+middleX+"' y1='"+middleY+"' x2='"+(middleX+Math.cos(sita)*lineLen)+"' y2='"+(middleY-(Math.sin(sita)*lineLen))+"' stroke='#000000'/>");
    sfile.append("\n");
    sfile.append("<text x='"+(middleX+Math.cos(sita)*textLen)+"' y='"+(middleY-(Math.sin(sita)*textLen))+"' space='preserve' font-family='Tahoma' font-size='21' fill='red' stroke='red' baseline-shift='baseline' >"+percent+"%</text>");
   }else if ((textRadian>(Math.PI/2)&&textRadian<Math.PI)){
    sfile.append("<line x1='"+middleX+"' y1='"+middleY+"' x2='"+(middleX-Math.cos(sita)*lineLen)+"' y2='"+(middleY-(Math.sin(sita)*lineLen))+"' stroke='#000000'/>");
    sfile.append("\n");
    sfile.append("<text x='"+(middleX-Math.cos(sita)*textLen)+"' y='"+(middleY-(Math.sin(sita)*textLen))+"' space='preserve' font-family='Tahoma' font-size='21' fill='red' stroke='red' baseline-shift='baseline' >"+percent+"%</text>");
   }else if ((textRadian>(Math.PI)&&textRadian<(Math.PI*3/2))){
    sfile.append("<line x1='"+middleX+"' y1='"+middleY+"' x2='"+(middleX-Math.cos(sita)*lineLen)+"' y2='"+(middleY+(Math.sin(sita)*lineLen))+"' stroke='#000000'/>");
    sfile.append("\n");
    sfile.append("<text x='"+(middleX-Math.cos(sita)*textLen)+"' y='"+(middleY+(Math.sin(sita)*textLen))+"' space='preserve' font-family='Tahoma' font-size='21' fill='red' stroke='red' baseline-shift='baseline' >"+percent+"%</text>");
   }else if((textRadian>(Math.PI*3/2)&&textRadian<(Math.PI*2))){
    sfile.append("<line x1='"+middleX+"' y1='"+middleY+"' x2='"+(middleX+Math.cos(sita)*lineLen)+"' y2='"+(middleY+Math.sin(sita)*lineLen)+"' stroke='#000000'/>");
    sfile.append("\n");
    sfile.append("<text x='"+(middleX+Math.cos(sita)*textLen)+"' y='"+(middleY+(Math.sin(sita)*textLen))+"' space='preserve' font-family='Tahoma' font-size='21' fill='red' stroke='red' baseline-shift='baseline' >"+percent+"%</text>");
   }
   sfile.append("\n");
   if(getRadian(percents[0])>Math.PI){
   sfile.append("<path d='M "+x0+" "+y0+" L "+(x0+r)+" "+r+" A "+r+" "+r+" 0 1 0 "+x1+" "+y1+" L "+x0+" "+y0+" z' fill='"+colors[0]+"'/>");
   }else{
   sfile.append("<path d='M "+x0+" "+y0+" L "+(x0+r)+" "+r+" A "+r+" "+r+" 0 0 0 "+x1+" "+y1+" L "+x0+" "+y0+" z' fill='"+colors[0]+"'/>");
   }
   sfile.append("\n");
   }
   sfile.append("<rect x='"+(x0+2*r)+"' y='"+(y0-r/2.0+N)+"' width='60' height='30' fill='"+colors[i]+"' stroke='#FFFFFF' stroke-dasharray='1,1' />");
   sfile.append("\n");
   sfile.append("<text x='"+(x0+2*r+80)+"' y='"+(y0-r/2.0+N+25)+"' space='preserve' font-family='宋体' font-size='28' fill='"+colors[0]+"' stroke='#000000' stroke-dasharray='1,1' baseline-shift='baseline'>"+names[0]+"</text>");
   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<(Math.PI/2))){
    sfile.append("<line x1='"+middleX+"' y1='"+middleY+"' x2='"+(middleX+Math.cos(sita)*lineLen)+"' y2='"+(middleY-(Math.sin(sita)*lineLen))+"' stroke='#000000'/>");
    sfile.append("\n");
    sfile.append("<text x='"+(middleX+Math.cos(sita)*textLen)+"' y='"+(middleY-(Math.sin(sita)*textLen))+"' space='preserve' font-family='Tahoma' font-size='21' fill='red' stroke='red' baseline-shift='baseline' >"+percent+"%</text>");
   }else if ((textRadian>(Math.PI/2)&&textRadian<Math.PI)){
    sfile.append("<line x1='"+middleX+"' y1='"+middleY+"' x2='"+(middleX-Math.cos(sita)*lineLen)+"' y2='"+(middleY-(Math.sin(sita)*lineLen))+"' stroke='#000000'/>");
    sfile.append("\n");
    sfile.append("<text x='"+(middleX-Math.cos(sita)*textLen)+"' y='"+(middleY-(Math.sin(sita)*textLen))+"' space='preserve' font-family='Tahoma' font-size='21' fill='red' stroke='red' baseline-shift='baseline' >"+percent+"%</text>");
   }else if ((textRadian>(Math.PI)&&textRadian<(Math.PI*3/2))){
    sfile.append("<line x1='"+middleX+"' y1='"+middleY+"' x2='"+(middleX-Math.cos(sita)*lineLen)+"' y2='"+(middleY+(Math.sin(sita)*lineLen))+"' stroke='#000000'/>");
    sfile.append("\n");
    sfile.append("<text x='"+(middleX-Math.cos(sita)*textLen)+"' y='"+(middleY+(Math.sin(sita)*textLen))+"' space='preserve' font-family='Tahoma' font-size='21' fill='red' stroke='red' baseline-shift='baseline' >"+percent+"%</text>");
   }else if((textRadian>(Math.PI*3/2)&&textRadian<(Math.PI*2))){
    sfile.append("<line x1='"+middleX+"' y1='"+middleY+"' x2='"+(middleX+Math.cos(sita)*lineLen)+"' y2='"+(middleY+Math.sin(sita)*lineLen)+"' stroke='#000000'/>");
    sfile.append("\n");
    sfile.append("<text x='"+(middleX+Math.cos(sita)*textLen)+"' y='"+(middleY+(Math.sin(sita)*textLen))+"' space='preserve' font-family='Tahoma' font-size='21' fill='red' stroke='red' baseline-shift='baseline' >"+percent+"%</text>");
   }
  sfile.append("\n");
  // 参数 1 表示 画大于180的弧, 0 表示画小于180的弧 (这个地方比较重要)
  if(getRadian(percents[i])>Math.PI){
   sfile.append("<path d='M "+x0+" "+y0+" L "+x1+" "+y1+" A "+r+" "+r+" 0 1 0 "+(x1=x0+getCos(radian)*r)+" "+(y1=y0-getSin(radian)*r)+" L "+x0+" "+y0+" z' fill='"+colors[i]+"'/>");
  }else{
    sfile.append("<path d='M "+x0+" "+y0+" L "+x1+" "+y1+" A "+r+" "+r+" 0 0 0 "+(x1=x0+getCos(radian)*r)+" "+(y1=y0-getSin(radian)*r)+" L "+x0+" "+y0+" z' fill='"+colors[i]+"'/>");
  }
  sfile.append("\n");
  }
  N+=50;
   sfile.append("<rect x='"+(x0+2*r)+"' y='"+(y0-r/2.0+N)+"' width='60' height='30' fill='"+colors[i]+"' stroke='#FFFFFF' stroke-dasharray='1,1' />");
   sfile.append("\n");
   sfile.append("<text x='"+(x0+2*r+80)+"' y='"+(y0-r/2.0+N+25)+"' space='preserve' font-family='宋体' font-size='28' fill='"+colors[0]+"' stroke='#000000' stroke-dasharray='1,1' baseline-shift='baseline'>"+names[i]+"</text>");
   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<data.length;i++){
 sum+=data[i];
 }
 for(int i=0;i<data.length;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图形,然后将断层的扇形的代码,重新倒序排列一下.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
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("<svg xmlns:svg='http://www.w3.org/2000/svg'");
  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("<defs></defs>");
  sfile.append("\n");
  String path = createPath(502, 300,300, 150, percents);
  sfile.append(path);
  sfile.append("</g>");
  sfile.append("\n");
  sfile.append("</svg>");
  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("<g stroke-width='1' stroke='#000000' transform='matrix(1,0,0,1,1.638,-9.83)' xmlns='http://www.w3.org/2000/svg'>");
  sfile.append("\n");
  for(int i=0;i<percents.length;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<Math.PI/2){
      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<Math.PI*3/2){
      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<Math.PI*2){
      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("<g fill='"+colors[i]+"' >");
     sfile.append("\n");
     sfile.append("<path d='M "+x0+" "+y0+" L "+(x0+langR)+" "+y0+" A "+langR+" "+shortR+" 0 1 0 "+xBottom+" "+yBottom+" z' />");
     sfile.append("\n");
     sfile.append("<path d='M "+(x0+langR)+" "+(y0-50)+" A "+langR+" "+shortR+" 0 1 0 "+xBottom+" "+(yBottom-50)+" L "+xBottom+" "+yBottom+" A "+langR+" "+shortR+" 0 1 1 "+(x0+langR)+" "+y0+" z' />");
     sfile.append("\n");
     sfile.append("<path d='M "+x0+" "+(y0-50)+" L "+(x0+langR)+" "+(y0-50)+" A "+langR+" "+shortR+" 0 1 0 "+xBottom+" "+(yBottom-50)+" z' />");
     sfile.append("\n");
     sfile.append("</g>");
     sfile.append("\n");
    }else{
     sfile.append("<g fill='"+colors[i]+"' >");
     sfile.append("\n");
     sfile.append("<path d='M "+x0+" "+y0+" L "+(x0+langR)+" "+y0+" A "+langR+" "+shortR+" 0 0 0 "+xBottom+" "+yBottom+" z' />");
     sfile.append("\n");
     sfile.append("<path d='M "+(x0+langR)+" "+(y0-50)+" A "+langR+" "+shortR+" 0 0 0 "+xBottom+" "+(yBottom-50)+" L "+xBottom+" "+yBottom+" A "+langR+" "+shortR+" 0 0 1 "+(x0+langR)+" "+y0+" z' />");
     sfile.append("\n");
     sfile.append("<path d='M "+x0+" "+(y0-50)+" L "+(x0+langR)+" "+(y0-50)+" A "+langR+" "+shortR+" 0 0 0 "+xBottom+" "+(yBottom-50)+" z' />");
     sfile.append("\n");
     sfile.append("</g>");
     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<Math.PI/2){
      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<Math.PI*3/2){
      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("<g fill='"+colors[i]+"' >");
     sfile.append("\n");
     sfile.append("<path d='M "+x0+" "+y0+" L "+xBottom+" "+yBottom+" A "+langR+" "+shortR+" 0 1 0 "+xBottom1+" "+yBottom1+" z' />");
     sfile.append("\n");
     sfile.append("<path d='M "+(xBottom)+" "+(yBottom-50)+" A "+langR+" "+shortR+" 0 1 0 "+xBottom1+" "+(yBottom1-50)+" L "+xBottom1+" "+yBottom1+" A "+langR+" "+shortR+" 0 1 1 "+xBottom+" "+yBottom+" z' />");
     sfile.append("\n");
     sfile.append("<path d='M "+x0+" "+(y0-50)+" L "+(xBottom)+" "+(yBottom-50)+" A "+langR+" "+shortR+" 0 1 0 "+xBottom1+" "+(yBottom1-50)+" z' />");
     sfile.append("\n");
     sfile.append("</g>");
     sfile.append("\n");
    }else{
     System.out.println("小于pi");
     sfile.append("<g fill='"+colors[i]+"' >");
     sfile.append("\n");
     sfile.append("<path d='M "+x0+" "+y0+" L "+xBottom+" "+yBottom+" A "+langR+" "+shortR+" 0 0 0 "+xBottom1+" "+yBottom1+" z' />");
     sfile.append("\n");
     sfile.append("<path d='M "+(xBottom)+" "+(yBottom-50)+" A "+langR+" "+shortR+" 0 0 0 "+xBottom1+" "+(yBottom1-50)+" L "+xBottom1+" "+yBottom1+" A "+langR+" "+shortR+" 0 0 1 "+xBottom+" "+yBottom+" z' />");
     sfile.append("\n");
     sfile.append("<path d='M "+x0+" "+(y0-50)+" L "+(xBottom)+" "+(yBottom-50)+" A "+langR+" "+shortR+" 0 0 0 "+xBottom1+" "+(yBottom1-50)+" z' />");
     sfile.append("\n");
     sfile.append("</g>");
     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<data.length;i++){
    sum+=data[i];
  }
  for(int i=0;i<data.length;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图形:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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图表的全部内容,希望大家喜欢。

延伸 · 阅读

精彩推荐