zoukankan      html  css  js  c++  java
  • 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(" ");
      sfile.append("<svg xmlns:svg='http://www.w3.org/2000/svg'");
      sfile.append(" ");
            sfile.append("xmlns='http://www.w3.org/2000/svg'");
            sfile.append(" ");
            sfile.append("xmlns:xlink='http://www.w3.org/1999/xlink'");
            sfile.append(" ");
            sfile.append("xml:space='default'");
            sfile.append(" ");
            sfile.append("version='1.1'  width='100%' height='100%' viewBox='0 0 2024 570'>");
            sfile.append(" ");
            sfile.append("<defs></defs>");
            sfile.append(" ");
            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(" ");
            //循环创造path标签.
            String path =creatPath(502, 300, 300, percents,names);//中心点式503,300.
            sfile.append(path);
            sfile.append("</g>");
            sfile.append(" ");
            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(" ");
                  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(" ");
                 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(" ");
                 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(" ");
                 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(" ");
              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(" ");
              }
             
              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(" ");
              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(" ");
             
          }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(" ");
                  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(" ");
                 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(" ");
                 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(" ");
                 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(" ");
           // 参数 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+=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(" ");
              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(" ");
          }
          
         }
         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());
      }
     }
    }

  • 相关阅读:
    jmeter上传和下载、webservice、数据库连接 -- 9
    jmeter cookies和token -- 8
    java 获得 微信 UserId
    让textarea根据文本的长度自动调整它的高度
    oracle 连接数据库并查询,返回List<Map<String, Object>> 数据
    POI 4.0 读取Excel
    excel (2)
    导出 doc
    sui Mobile 试玩
    oracle 与 前台 md5
  • 原文地址:https://www.cnblogs.com/jhmyuan/p/4709463.html
Copyright © 2011-2022 走看看