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圖表的全部內容,希望大家喜歡。