java生成餅圖svg及JFreeChart生成svg圖表
Jfreechart本身不能生成SVG圖形,但是可以借助另外一個東西,輔助生成.好像是這個:batik ,具體代碼請看下文
一:Java生成svg餅圖,附帶了一個標(biāo)簽顯示各個顏色代表的部分
package com.tellhow.svg;
import java.io.File;
import java.io.FileOutputStream;
/**
*
* @author 風(fēng)絮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");
//循環(huán)創(chuàng)造path標(biāo)簽.
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 中心點橫坐標(biāo)
* @param y0 中心點縱坐標(biāo)
* @param r 半徑
* @param percents 百分比數(shù)組
* @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坐標(biāo)
double y1=0; //新扇形的y坐標(biāo)
double middleX=0; //文本顯示的坐標(biāo),包括豎線顯示的坐標(biāo)
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;//獲得精確到兩位小數(shù)點的坐標(biāo).
k=Math.abs((middleY-y0)/(middleX-x0));//獲得扇形終點的坐標(biāo),與中心點連成的直線的斜率.(取正值)
double sita= Math.atan(k);//求斜角
double lineLen=50;
double textLen=70;
if(radian<6){
lineLen=90;
textLen=110;//控制指示線的長度,與文字的位置
}
if(percents[i]!=0){//當(dāng)一個類型為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){//當(dāng)一個類型為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");
// 參數(shù) 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這個東西,里面的一些標(biāo)簽都干什么用的.等等.) 3D的這個,生成的效果圖,會有斷層的效果,主要是出現(xiàn)在第一現(xiàn)象和第四象限,即如果第一象限或第四象限,有兩個扇形的話,就會出現(xiàn)斷層,可以用這個工具進(jìn)行調(diào)整: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("<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坐標(biāo)
yBottom = y0-shortR;//底面的y坐標(biāo)
}else if(radian==Math.PI*3/2){
xBottom = x0;//底面的x坐標(biāo)
yBottom = y0+shortR;//底面的y坐標(biāo)
} 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坐標(biāo)
yBottom = y0-(tanRadian*langR*shortR)/Math.sqrt(sqValue);//底面的y坐標(biāo)
}
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坐標(biāo)
yBottom1= y0-shortR;//底面的y坐標(biāo)
}else if(radian==Math.PI*3/2){
xBottom1 = x0;//底面的x坐標(biāo)
yBottom1 = y0+shortR;//底面的y坐標(biāo)
} 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坐標(biāo)
yBottom1 = y0-(tanRadian*langR*shortR)/Math.sqrt(sqValue);//底面的y坐標(biāo)
}
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動態(tài)生成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();
// 創(chuàng)建JFreeChart對象,在內(nèi)存中間創(chuàng)建出對應(yīng)的圖像
JFreeChart chart = ChartFactory.createBarChart3D("水果產(chǎn)量圖", // 圖表標(biāo)題
"水果", // 目錄軸的顯示標(biāo)簽
"產(chǎn)量", // 數(shù)值軸的顯示標(biāo)簽
dataset, // 數(shù)據(jù)集
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 {
// 得到數(shù)據(jù)Dataset
CategoryDataset dataset = getDataSet();
// 創(chuàng)建JFreeChart對象,在內(nèi)存中間創(chuàng)建出對應(yīng)的圖像
JFreeChart chart = ChartFactory.createBarChart3D("水果產(chǎn)量圖", // 圖表標(biāo)題
"水果", // 目錄軸的顯示標(biāo)簽
"產(chǎn)量", // 數(shù)值軸的顯示標(biāo)簽
dataset, // 數(shù)據(jù)集
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) {
}
}
}
/**
* 獲取一個演示用的簡單數(shù)據(jù)集對象
*
* @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;
}
/**
* 獲取一個演示用的組合數(shù)據(jù)集對象
*
* @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,當(dāng)你查看的時候不支持中文. 我記得好像是如果是安裝的adobe的那個查看器,在IE里面瀏覽的話好像是中文亂碼,如果用另外一個叫做 Renesis SVG Player ,這個查看器就是支持中文的.
以上內(nèi)容就是java生成餅圖svg及JFreeChart生成svg圖表的全部內(nèi)容,希望大家喜歡。
相關(guān)文章
Windows10 Java環(huán)境變量配置過程圖解
這篇文章主要介紹了Windows10 Java環(huán)境變量配置過程圖解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-07-07
一篇文章帶你入門Java數(shù)據(jù)結(jié)構(gòu)
這篇文章主要介紹了Java常見數(shù)據(jù)結(jié)構(gòu)面試題,帶有答案及解釋,希望對廣大的程序愛好者有所幫助,同時祝大家有一個好成績,需要的朋友可以參考下,希望可以幫助到你2021-08-08
Java中的Lambda表達(dá)式及其應(yīng)用小結(jié)
Java中的Lambda表達(dá)式是一項極具創(chuàng)新性的特性,它使得Java代碼更加簡潔和高效,尤其是在集合操作和并行處理方面,這篇文章主要介紹了Java中的Lambda表達(dá)式及其應(yīng)用,需要的朋友可以參考下2025-04-04
Java Comparable及Comparator接口區(qū)別詳解
這篇文章主要介紹了Java Comparable及Comparator接口區(qū)別詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-07-07
springboot?vue測試前端項目管理列表分頁功能實現(xiàn)
這篇文章主要為大家介紹了springboot?vue測試前端項目列表分頁功能實現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
Mybatis + js 實現(xiàn)下拉列表二級聯(lián)動效果
這篇文章給大家介紹基于Mybatis + js 實現(xiàn)下拉列表二級聯(lián)動效果,實現(xiàn)代碼分為前端界面實現(xiàn)和后端處理方法,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2021-06-06

