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("<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的更多相关文章
- java生成饼图
pom.xml文件导入依赖包 <!-- https://mvnrepository.com/artifact/org.jfree/jfreechart --> <dependency ...
- Java生成和操作Excel文件(转载)
Java生成和操作Excel文件 JAVA EXCEL API:是一开放源码项目,通过它Java开发人员可以读取Excel文件的内容.创建新的Excel文件.更新已经存在的Excel文件.使用该A ...
- 利用JAVA生成二维码
本文章整理于慕课网的学习视频<JAVA生成二维码>,如果想看视频内容请移步慕课网. 维基百科上对于二维码的解释. 二维条码是指在一维条码的基础上扩展出另一维具有可读性的条码,使用黑白矩形图 ...
- Java生成验证码原理(jsp)
验证码的作用: 验证码是Completely Automated Public Turing test to tell Computers and Humans Apart(全自动区分计算机和人类的 ...
- JAVA生成条形码
1.下载生成条形码所需要的jar包barcode4j.jar: 2.java生成条形码代码 import java.awt.image.BufferedImage;import java.io.Fil ...
- Java生成CSV文件实例详解
本文实例主要讲述了Java生成CSV文件的方法,具体实现步骤如下: 1.新建CSVUtils.java文件: package com.saicfc.pmpf.internal.manage.utils ...
- java 生成8位数字作为UID
java 生成8位数字作为UUID: /*** * 生成uid 8位数字 */public static String generateUID(){ Random random = new Rando ...
- java生成随机序列号
1.java生成随机序列号 String deleteUuid = UUID.randomUUID().toString(); 引用Jar包 //java-uuid-generator-3.1.3.j ...
- java生成简单Excel工作薄
前言: 代码都是建立在实际需求上的,上周做完一个调外部电影券接口的项目,这周产品又要excel表格,大致内容为:券所属影院.图片URL.等信息制作为excel表格,把每次同步过来的数据给他分析. jx ...
随机推荐
- 「LuoguP4779」 【模板】单源最短路径(标准版)
Description 2018 年 7 月 19 日,某位同学在 NOI Day 1 T1 归程 一题里非常熟练地使用了一个广为人知的算法求最短路. 然后呢? 100→60: Ag→Cu: 最终,他 ...
- 平衡二叉树、B树、B+树、B*树、LSM树简介
平衡二叉树是基于分治思想采用二分法的策略提高数据查找速度的二叉树结构.非叶子结点最多只能有两个子结点,且左边子结点点小于当前结点值,右边子结点大于当前结点树,并且为保证查询性能增增删结点时要保证左右两 ...
- css画三角的原理
当我们设置一个div其width与height为100px,并且设置其四边框的宽度为100px,且分别设置其颜色后,我们可以看到如下的一张图片 此时如果设置这个div的height为0的话,其他不变, ...
- 011--python基础知识
一.python类型 编译型和解释型 编译型: 优点:编译器一般会有预编译的过程对代码进行优化.因为编译只做一次,运行时不需要编译,所以编译型语言的程序执行效率高.可以脱离语言环境独立运行. 缺点:编 ...
- https://www.luogu.org/blog/An-Amazing-Blog/mu-bi-wu-si-fan-yan-ji-ge-ji-miao-di-dong-xi
https://www.luogu.org/blog/An-Amazing-Blog/mu-bi-wu-si-fan-yan-ji-ge-ji-miao-di-dong-xi
- 793. Preimage Size of Factorial Zeroes Function
Let f(x) be the number of zeroes at the end of x!. (Recall that x! = 1 * 2 * 3 * ... * x, and by con ...
- python __builtins__ credits类 (15)
15.'credits', 信用 class _Printer(builtins.object) | interactive prompt objects for printing the licen ...
- poj 3683 Priest John's Busiest Day【2-SAT+tarjan+拓扑】
转换成2-SAT模型,建边是如果时间(i,j)冲突就连边(i,j'),其他同理 tarjan缩点,判可行性 返图拓扑,输出方案 #include<iostream> #include< ...
- 一个关于国密SM4的故事
一个关于国密SM4的故事 我的名字叫SM4,我还有三位兄长,分别是大哥SM1, 二哥SM2, 和三哥SM3.说起我的名字,故事要回到2006年的时候,我出生的时候并不是叫SM4的,而是叫做SMS4.只 ...
- redis查数据
1 连接服务 [root@redis1-20 ~]# telnet 127.0.0.1 6380 Trying 127.0.0.1... Connected to 127.0.0.1. Escape ...