新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论SVG, GML, X3D, VRML, VML, XAML, AVALON, Batik等基于XML的图形技术,以及有关GIS的应用。
    [返回] 中文XML论坛 - 专业的XML技术讨论区XML.ORG.CN讨论区 - 高级XML应用『 SVG/GML/VRML/X3D/XAML 』 → [转帖]JAVA生成SVG图表实例之柱状图 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 5862 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: [转帖]JAVA生成SVG图表实例之柱状图 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     SCYANGYU 帅哥哟,离线,有人找我吗?处女座1971-9-20
      
      
      威望:7
      等级:大四(每天看1小时莱昂氏)
      文章:217
      积分:1281
      门派:XML.ORG.CN
      注册:2005/2/17

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给SCYANGYU发送一个短消息 把SCYANGYU加入好友 查看SCYANGYU的个人资料 搜索SCYANGYU在『 SVG/GML/VRML/X3D/XAML 』的所有贴子 引用回复这个贴子 回复这个贴子 查看SCYANGYU的博客楼主
    发贴心情 [转帖]JAVA生成SVG图表实例之柱状图

    JAVA生成SVG图表实例之柱状图

    做系统的时候都要配合报表展示一些图表,例如柱状图、饼图还有曲线图,以前是用VML做成通用的,数值的计算和VML在页面上的显示,全部是用javascript做的,可是VML中的文字定位不是特别舒服,javascript计算数字也不是很精确。最近学了几天SVG,觉得不错,所以就想用JAVA生成SVG文件,然后显示,网上没有类似的文章,所以我就把自己的第一个作品放出来,希望大家能够提点向我提电意见,改进。我以后会陆续放做好的饼图、曲线图。我相信这是国内第一个类似的程序,希望能够起到抛砖引玉的作用。

    这个程序能够生成单柱柱状图,也能生成多柱柱状图。我的注释写得相当的详细,相信大家都能看的懂。我没有使用APACHE的Batik来生成SVG文件,而是先组成字符串然后生成SVG文件。以下是源码,我做的时候是按照12组数据设计的,当数据少的话,柱子会很宽,我正在改进。

    package com.hhh.Paint;

    import java.io.File;
    import java.io.FileOutputStream;
    import java.math.BigDecimal;

    /**
    * 该类是使用SVG画动态柱状图,只需调用本类的静态方法createSVG(String fileRealPath,String[]
    * pData,String[] pDataName)即可,我没有使用APACHE提供的SVG类库来生成SVG文件,只是将所有SVG描述用字符串返回
    *
    * @author 顾国勇
    * @version 1.0
    */
    public class PaintHistogram {

    /**
      * 正值所用的12种颜色
      */
    public static String[][] color = { { "#ff2222", "#ffaaaa", "#aa1111" },
       { "#d0b83a", "#f2e692", "#9f8703" },
       { "#ffdf00", "#fef195", "#ce9a31" },
       { "#22FF22", "#aaffaa", "green" },
       { "#ff9e00", "#ffbe08", "#bd7500" },
       { "#799AE1", "#9aabEe", "#5778a1" },
       { "#99c741", "#aef292", "#3e941b" },
       { "#d0b83a", "#f2e692", "#9f8703" },
       { "#319a00", "#66cc00", "#297110" },
       { "#c27f34", "#d6a97b", "#82522b" },
       { "#2222ff", "#aaaaff", "#1111aa" },
       { "#ff2222", "#ffaaaa", "#aa1111" } }; //,{"#99c741","#aef292","#3e941b"}

    /**
      * 负值所用的颜色
      */
    public static String[][] colorNeg = { { "black", "#4F4F4F", "#757575" },
       { "#1A0B0F", "#4F4F4F", "#757575" } };

    /**
      * 存放转换成double型的数据,用于单例柱形
      */
    public static double[] data;

    /**
      * 存放转换成double型的数据,用于多例柱形
      */
    public static double[][] data1;

    /**
      * 数据总数,默认值为0
      */
    public static int dataNum = 0;

    /**
      * 默认柱状图X轴的起始X值
      */
    public static double HistogramXSx = 50.0;

    /**
      * 默认柱状图X轴的Y值
      */
    public static double HistogramXy = 440.0;

    /**
      * 将元数据从String转换成double,用于单例柱形
      *
      * @param data
      *            字符串数组形式的元数据
      * @return 转换好的数据
      */
    static double[] convertDataToDouble(String[] data) {
      double[] dData = new double[data.length];
      dataNum = 0;
      for (int i = 0; i < data.length; i++) {
       if (data[i] != null && !data[i].equalsIgnoreCase("")
         && !data[i].equalsIgnoreCase(" ")) {
        dData[i] = Double.valueOf(data[i]).doubleValue();
        dataNum += 1;
       } else {
        dData[i] = new Double(0.0).doubleValue();
        dataNum += 1;
       }
      }
      return dData;
    }

    /**
      * 将元数据从String转换成double,用于多例柱形
      *
      * @param data
      *            字符串数组形式的元数据
      * @return 转换好的数据
      */
    static double[][] convertDataToDouble(String[][] data) {
      double[][] dData = new double[data.length][data[0].length];
      dataNum = 0;
      for (int i = 0; i < data.length; i++) {
       for (int j = 0; j < data[i].length; j++) {
        if (data[i][j] != null && !data[i][j].equalsIgnoreCase("")
          && !data[i][j].equalsIgnoreCase(" ")) {
         dData[i][j] = Double.parseDouble(data[i][j]);//Double.valueOf(data[i][j]).doubleValue();
         dataNum += 1;
        } else {
         dData[i][j] = new Double(0.0).doubleValue();
         dataNum += 1;
        }
       }
      }
      return dData;
    }

    /**
      * @param fileRealPath
      *            指定的SVG文件的全路径,用于单例柱形
      * @param pData
      *            元数据数组
      * @param pDataName
      *            元数据数组名称
      */
    public static void createSVG(String fileRealPath, String[] pData,
       String[] pDataName) throws Exception {
      String sFile = paint(pData, pDataName);
      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());
      }

    }

    /**
      * @param fileRealPath
      *            指定的SVG文件的全路径,用于多例柱形
      * @param pData
      *            元数据数组
      * @param pDataName
      *            元数据数组名称
      */
    public static void createSVG(String fileRealPath, String[][] pData,
       String[] pDataName) {
      try {
       String sFile = paint(pData, pDataName);

       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("createSVG:" + ex.getMessage());
      }

    }

    /**
      * 根据原始数据过滤出最大最小值,已经考虑了数据正负的各种情况(全是正数,全是负数,有正有负),如果元数据中最大值或最小值的绝对值是小于1的,那最后返回的相应值的绝对值是1;
      * 如果最大或最小的绝对值小于100,那最后返回的相应值的绝对值是10的倍数;如果最大或最小的绝对值大于100,那最后返回的相应值的绝对值是50的倍数
      *
      * @param data
      *            <B>原始数据 </B>
      * @return <B>包含绝对值最大的值 </B>
      */
    static double getValueMax(double[] pData) {
      //存放所有数据值
      double max = pData[0];
      double min = pData[0];

      for (int i = 0; i < pData.length; i++) {
       if (pData[i] > max)
        max = pData[i];
       if (pData[i] < min)
        min = pData[i];
      }

      //全是负的
      if (max <= 0 && min < 0) {
       min = Math.floor(min);
       double tMin = Math.abs(min);
       max = 0;
       if (tMin <= 1)
        min = -1;
       else {
        min = -(tMin < 100 ? Math.ceil(tMin / 10) * 10 : Math
          .ceil(tMin / 50) * 50);
       }
      }
      //有正有负
      if (min < 0 && max > 0) {
       max = Math.ceil(max);
       if (max <= 1)
        max = 1;
       else {
        max = max < 100 ? Math.ceil(max / 10) * 10 : Math
          .ceil(max / 50) * 50;
       }

       min = Math.abs(Math.floor(min));
       if (min <= 1)
        min = -1;
       else {
        min = -(min < 100 ? Math.ceil(min / 10) * 10 : Math
          .ceil(min / 50) * 50);
       }
      }
      //全是正的
      if (min >= 0 && max >= 0) {
       if (max == 0.0) {
        max = min = 0.0;
       } else {
        if (max <= 1)
         max = 1;
        else {
         max = max < 100 ? Math.ceil(max / 10) * 10 : Math
           .ceil(max / 50) * 50;
        }
       }
      }

      double absMax = Math.abs(max) > Math.abs(min) ? Math.abs(max) : Math
        .abs(min);
      return absMax;
    }

    /**
      * 类初始化,主要是声明了文件开头和滤镜,对于画正负Y轴都通用
      *
      * @return SVG文件头
      */
    static String initialize() {
      //文件头声明
      StringBuffer sFile = new StringBuffer();
      sFile.append("<?xml version='1.0' encoding='UTF-8'?>");
      sFile.append("\n");
      sFile
        .append("<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.0//EN' 'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd'>");
      sFile.append("\n");
      sFile
        .append("<svg width='700' height='500' viewBox='0 0 700 500' xmlns='http://www.w3.org/2000/svg'>");
      sFile.append("\n");
      sFile.append("<desc>Histogram</desc>");
      sFile.append("\n");
      sFile
        .append("<rect x='0' y='0' width='700' height='500' fill='none' stroke='blue' stroke-width='1'/>");
      sFile.append("\n");
      //定义滤镜和箭头
      sFile.append("<defs>");
      sFile.append("\n");
      sFile
        .append("  <marker id='Triangle' viewBox='0 0 10 10' refX='0' refY='5' markerUnits='strokeWidth' markerWidth='4' markerHeight='10' orient='auto'>");
      sFile.append("\n");
      sFile.append("   <path d='M 0 0 L 10 5 L 0 10 z'/>");
      sFile.append("\n");
      sFile.append("  </marker>");
      sFile.append("\n");
      sFile.append("  <linearGradient id='linear1'>");
      sFile.append("\n");
      sFile.append("     <stop offset='0%' stop-color='red'/>");
      sFile.append("\n");
      sFile.append("       <stop offset='30%' stop-color='white'/>");
      sFile.append("\n");
      sFile.append("       <stop offset='100%' stop-color='blue'/>");
      sFile.append("\n");
      sFile.append("    </linearGradient>");
      sFile.append("\n");
      sFile
        .append("    <filter id='MyFilter' filterUnits='userSpaceOnUse' x='0' y='0' width='100%' height='100%'>");
      sFile.append("\n");
      sFile
        .append("   <feGaussianBlur in='SourceAlpha' stdDeviation='3' result='blur'/>");
      sFile.append("\n");
      sFile
        .append("   <feOffset in='blur' dx='4' dy='4' result='offsetBlur'/>");
      sFile.append("\n");
      sFile.append("\n");
      sFile
        .append("   <feSpecularLighting in='blur' surfaceScale='.5' specularConstant='2.5' specularExponent='128' lighting-color='#bbbbbb'  result='specOut'>");
      sFile.append("\n");
      sFile.append("    <fePointLight x='-600' y='-100' z='2200'/>");
      sFile.append("\n");
      sFile.append("   </feSpecularLighting>");
      sFile.append("\n");
      sFile
        .append("   <feComposite in='specOut' in2='SourceAlpha' operator='in' result='specOut'/>");
      sFile.append("\n");
      sFile
        .append("   <feComposite in='SourceGraphic' in2='specOut' operator='arithmetic' k1='0' k2='1' k3='1' k4='0' result='litPaint'/>");
      sFile.append("\n");
      sFile.append("   <feMerge>");
      sFile.append("\n");
      sFile.append("      <feMergeNode in='offsetBlur'/>");
      sFile.append("\n");
      sFile.append("        <feMergeNode in='litPaint'/>");
      sFile.append("\n");
      sFile.append("   </feMerge>");
      sFile.append("\n");
      sFile.append("  </filter>");
      sFile.append("\n");
      sFile.append("<script type=\"text/javascript\">");
      sFile.append("\n");
      sFile.append("<![CDATA[");
      sFile.append("\n");
      sFile.append("       function showValue(value) {");
      sFile.append("\n");
      sFile.append("        alert(value);");
      sFile.append("\n");
      sFile.append("       }");
      sFile.append("\n");
      sFile.append("]]>");
      sFile.append("\n");
      sFile.append("</script>");
      sFile.append("\n");
      sFile.append("</defs>");
      sFile.append("\n");
      //X轴
      sFile
        .append("<line x1='50' y1='440' x2='660' y2='440' stroke-width='2' stroke-opacity='.4' fill='blue' stroke='#333300' />");
      sFile.append("\n");
      //Y轴
      sFile
        .append("<line x1='50' y1='440' x2='50' y2='40' stroke-width='2' stroke-opacity='.4' fill='blue' stroke='#333300' />");
      sFile.append("\n");
      sFile
        .append("<line x1='60' y1='30' x2='60' y2='430' stroke-width='0.5'  stroke='#333300'/>");
      /* Y轴刻度线 */
      for (int i = 0; i < 11; i++) {
       double tempY1 = 40 + i * 40.0; //每根Y轴刻度线的起始位置
       sFile.append("<line  x1='50' y1='" + tempY1 + "' x2='60' y2='"
         + (tempY1 - 10) + "' stroke-width='1'  stroke='#333300'/>");
       sFile.append("<line x1='60' y1='" + (tempY1 - 10)
         + "' x2='670' y2='" + (tempY1 - 10)
         + "' stroke='#333300'/>");
       sFile.append("\n");
       //            sFile.append("<polygon points='50," + tempY1 + " 660," + tempY1
       //                    + " 670," + (tempY1 - 10) + " 60," + (tempY1 - 10)
       //                    + " ' ");
       //            sFile
       //            .append("
       // style='fill:rgb(37,170,219);stroke:rgb(37,170,219);stroke-width:1;fill-opacity:0.3;stroke-opacity:0;opacity:0.8'/>");
       //            sFile.append("\n");
      }

      return sFile.toString();

    }

    /**
      * @param args
      */
    public static void main(String[] args) {
      try {
       String[][] data = { { "54", "44", "122" }, { "", "12", "-468" },
         { "78", "520", "10" } };
       String[] data1 = { "54", "4424.225", "12200" ,"-4658" };

       String[] dataName = { "营业所一", "二二二二", "III" };
       PaintHistogram.createSVG("d:\\t1.svg", data, dataName);
       PaintHistogram.createSVG("d:\\t2.svg", data1, dataName);

      } catch (Exception ex) {
       System.out.print(ex.getMessage());
      }
    }

    /**
      * 画出柱状及刻度等,适用于X轴每格都只显示一个柱型
      *
      * @param pData
      *            元数据
      * @param pDataName
      *            元数据的名称
      */
    static String paint(String[] pData, String[] pDataName) throws Exception {
      StringBuffer sFile = new StringBuffer();
      data = convertDataToDouble(pData);

      double valueMM = getValueMax(data); //取得最大值
      sFile.append(initialize());
      //X Y步长
      double yStep = 400.0 / valueMM;
      double xStep = (new BigDecimal(600 / pDataName.length).setScale(3,
        BigDecimal.ROUND_HALF_UP)).doubleValue();

      double colWidth = xStep / 2; //柱型的宽度

      double colWidthPre = xStep / 4; //每个单元格起始与柱型的距离

      double colWidthNext = xStep / 4; //每个单元格结束与柱型的距离
      /* x轴刻度线 */
      for (int i = 0; i < pDataName.length; i++) {

       double tempX1 = i == 0 ? HistogramXSx + i * xStep : HistogramXSx
         + i * xStep + 10; //每根X轴刻度线的起始位置

       //double tempX2 = tempX1 + colWidthPre; //每根柱状的起始位置
       sFile.append("<line x1='" + tempX1 + "' y1='" + HistogramXy
         + "' x2='" + (tempX1 + 10.0) + "' y2='"
         + (HistogramXy - 10)
         + "' stroke-width='1'  stroke='#333300'/>");
       sFile.append("\n");
      }

      /* 画Y轴刻度值 */
      int maxValue = (int) valueMM;
      int valueX; //Y轴刻度值起始的X坐标
      String fontsize = "";
      if (maxValue > 10000) {
       valueX = 5;
       fontsize = "11px";
      } else {
       valueX = 15;
       fontsize = "13px";
      }
      for (int i = 0; i < 10; i++) {
       sFile.append("<text x='" + valueX + "' y='" + (45 + i * 40)
         + "' fill='black' font-family='Verdana' font-size='"
         + fontsize + "'>");
       sFile.append("\n");
       sFile.append((maxValue / 10) * (10 - i));
       sFile.append("\n");
       sFile.append("</text>");
       sFile.append("\n");
      }

      /* 画矩形 */
      sFile.append("<g style='filter:url(#MyFilter)'>");
      sFile.append("\n");
      for (int i = 0; i < pDataName.length; i++) {

       double tempX1 = i == 0 ? HistogramXSx + i * xStep : HistogramXSx
         + i * xStep + 10; //每根X轴刻度线的起始位置

       double tempX2 = tempX1 + colWidthPre; //每根柱状的起始位置
       double colHeight = Math.ceil(Math.abs(data[i]) * yStep);
       double tempY = 440 - colHeight;

       String[] colorHistogram; //三个柱面的颜色
       if (data[i] < 0) {
        colorHistogram = colorNeg[0];
        sFile.append(paintHistogram(colWidth, colHeight, tempX2, tempY,
          colorHistogram, data[i]));
       } else if (data[i] > 0) {
        int n = i % color.length;
        colorHistogram = color[n];
        sFile.append(paintHistogram(colWidth, colHeight, tempX2, tempY,
          colorHistogram, data[i]));
       }

       /* 添加X轴字段说明 字无法在一行内显示的话,需要换行 */
       int n = (int) xStep / 13;//每行显示几个字符
       int m = pDataName[i].length() % n == 0 ? pDataName[i].length() / n
         : (int) (pDataName[i].length() / n + 1);//总共显示几行
       int l = 0;//记录总共处理了多少字符
       if (m > 1) {
        sFile
          .append("<text fill='blue' font-size='15px' font-family='STFangsong'>");
        for (int j = 0; j < m; j++) {
         for (int z = 0; z < n; z++) {
          l = j * n + z;
          if (l == pDataName[i].length()) {
           break;
          }
          sFile.append("<tspan x='" + (tempX1 + z * 15) + "' y='"
            + (460 + j * 20) + "' >");
          sFile.append(pDataName[i].substring(l, l + 1));
          sFile.append("</tspan>");
         }
         if (l == pDataName[i].length()) {
          break;
         }
        }
        sFile.append("</text>");
        sFile.append("\n");
       } else {
        sFile
          .append("<text x='"
            + (5 + tempX1)
            + "' y='460' fill='blue' font-size='15px' font-family='STFangsong'>"
            + pDataName[i] + "</text>");
        sFile.append("\n");
       }
      }
      sFile.append("</g>");
      sFile.append("\n");
      sFile.append("</svg>");
      return sFile.toString();

    }

    /**
      * 画出柱状及刻度等,适用于X轴每格都显示多个柱型
      *
      * @param pData
      *            具体的元数据
      * @param pDataName
      *            元数据的名称
      */
    static String paint(String[][] pData, String[] pDataName) {
      StringBuffer sFile = new StringBuffer();
      data1 = convertDataToDouble(pData);
      //取得最大值

      double[] tempValue = new double[dataNum];
      for (int i = 0; i < data1.length; i++) {
       for (int j = 0; j < data1[i].length; j++) {
        tempValue[i * data1[i].length + j] = data1[i][j];
       }
      }
      double valueMM = getValueMax(tempValue);
      sFile.append(initialize());
      double yStep = 400.0 / valueMM;
      double xStep = (new BigDecimal(600 / pDataName.length).setScale(3,
        BigDecimal.ROUND_HALF_UP)).doubleValue();

      double colWidthSum = xStep / 2; //多个柱型的宽度之和
      double colWidthPre = xStep / 4; //每个单元格起始与柱形的距离
      double colWidthNext = xStep / 4; //每个单元格结束与柱形的距离
      double colWidth = colWidthSum / data1[0].length; //单个柱形的宽度

      /* x轴刻度线 */
      for (int i = 0; i < pDataName.length; i++) {
       double tempX1 = i == 0 ? HistogramXSx + i * xStep : HistogramXSx
         + i * xStep + 10; //每根X轴刻度线的起始位置
       //double tempX2 = tempX1 + colWidthPre; //每根柱形的起始位置
       sFile.append("<line x1='" + tempX1 + "' y1='" + HistogramXy
         + "' x2='" + (tempX1 + 10.0) + "' y2='"
         + (HistogramXy - 10)
         + "' stroke-width='1'  stroke='#333300'/>");
       sFile.append("\n");
      }

      /* 画Y轴刻度值 */
      int maxValue = (int) valueMM;
      int valueX;//Y轴刻度值起始的X坐标
      String fontsize = "";
      if (maxValue > 10000) {
       valueX = 5;
       fontsize = "11px";
      } else {
       valueX = 15;
       fontsize = "13px";
      }
      for (int i = 0; i < 10; i++) {
       sFile.append("<text x='" + valueX + "' y='" + (45 + i * 40)
         + "' fill='black' font-family='Verdana' font-size='"
         + fontsize + "'>");
       sFile.append("\n");
       sFile.append((maxValue / 10) * (10 - i));
       sFile.append("\n");
       sFile.append("</text>");
       sFile.append("\n");
      }

      /* 画矩形 */
      sFile.append("<g style='filter:url(#MyFilter)'>");
      sFile.append("\n");
      for (int i = 0; i < pDataName.length; i++) {
       //每根X轴刻度线的起始位置
       double tempX1 = i == 0 ? HistogramXSx + i * xStep : HistogramXSx
         + i * xStep + 10;
       for (int j = 0; j < data1[i].length; j++) {
        double tempX2 = tempX1 + colWidthPre + j * colWidth; //每根柱形的起始位置
        double colHeight = Math.ceil(Math.abs(data1[i][j]) * yStep);
        double tempY = 440 - colHeight;
        String[] colorHistogram; //三个柱面的颜色
        if (data1[i][j] < 0) {
         colorHistogram = colorNeg[0];
         sFile.append(paintHistogram(colWidth, colHeight, tempX2,
           tempY, colorHistogram, data1[i][j]));
        } else if (data1[i][j] > 0) {
         int n = j % color.length;
         colorHistogram = color[n];
         sFile.append(paintHistogram(colWidth, colHeight, tempX2,
           tempY, colorHistogram, data1[i][j]));
        }

       }

       /* 添加X轴字段说明 字无法在一行内显示的话,需要换行 */
       int n = (int) xStep / 13;//每行显示几个字符
       int m = pDataName[i].length() % n == 0 ? pDataName[i].length() / n
         : (int) (pDataName[i].length() / n + 1);//总共显示几行
       int l = 0;//记录总共处理了多少字符
       if (m > 1) {
        sFile
          .append("<text fill='blue' font-size='15px' font-family='STFangsong'>");
        for (int j = 0; j < m; j++) {
         for (int z = 0; z < n; z++) {
          l = j * n + z;
          if (l == pDataName[i].length()) {
           break;
          }
          sFile.append("<tspan x='" + (tempX1 + z * 15) + "' y='"
            + (460 + j * 20) + "' >");
          sFile.append(pDataName[i].substring(l, l + 1));
          sFile.append("</tspan>");
         }
         if (l == pDataName[i].length()) {
          break;
         }
        }
        sFile.append("</text>");
        sFile.append("\n");
       } else {
        sFile
          .append("<text x='"
            + (5 + tempX1)
            + "' y='460' fill='blue' font-size='15px' font-family='STFangsong'>"
            + pDataName[i] + "</text>");
        sFile.append("\n");
       }

      }
      sFile.append("</g>");
      sFile.append("\n");
      sFile.append("</svg>");
      return sFile.toString();

    }

    /**
      * 画单一柱形
      *
      * @param colWidth
      *            柱形宽度
      * @param colHeight
      *            柱形高度
      * @param x
      *            柱形X值
      * @param y
      *            柱形Y值
      * @param color
      *            柱形三个面的颜色
      * @param dataValue
      *            柱形代表的值
      * @return SVG字符串
      */
    static String paintHistogram(double colWidth, double colHeight, double x,
       double y, String[] color, double dataValue) {
      StringBuffer sFile = new StringBuffer();
      double dOffset = (colWidth / 3) > 10.0 ? 10.0 : (colWidth / 3);//斜面的偏移量
      sFile.append("<rect width='" + colWidth + "' height='" + colHeight
        + "' x='" + x + "' y='" + y + "' fill='" + color[0]
        + "' onclick='showValue(" + dataValue + ")'/>");
      sFile.append("\n");
      sFile.append("<polygon points='" + x + "," + y + " " + (x + dOffset)
        + "," + (y - dOffset) + " " + (x + dOffset + colWidth) + ","
        + (y - dOffset) + " " + (x + colWidth) + "," + y
        + "' style='fill:" + color[1] + ";stroke:" + color[1]
        + ";stroke-width:1;' onclick='showValue(" + dataValue + ")'/>");
      sFile.append("\n");
      sFile.append("<polygon points='" + (x + dOffset + colWidth) + ","
        + (y - dOffset) + " " + (x + colWidth) + "," + y + " "
        + (x + colWidth) + "," + 440 + " " + (x + dOffset + colWidth)
        + "," + (y - dOffset + colHeight) + "' style='fill:" + color[2]
        + ";stroke:" + color[2]
        + ";stroke-width:1;' onclick='showValue(" + dataValue + ")'/>");
      return sFile.toString();
    }
    }

    作者Blog:http://blog.csdn.net/turing_gu/

    http://dev.csdn.net/article/62/article/35/35577.shtm


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    http://borland.mblogger.cn/scyangyu/

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/2/19 19:02:00
     
     henrybenben 帅哥哟,离线,有人找我吗?
      
      
      等级:大二(研究C++)
      文章:50
      积分:257
      门派:XML.ORG.CN
      注册:2005/4/13

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给henrybenben发送一个短消息 把henrybenben加入好友 查看henrybenben的个人资料 搜索henrybenben在『 SVG/GML/VRML/X3D/XAML 』的所有贴子 引用回复这个贴子 回复这个贴子 查看henrybenben的博客2
    发贴心情 
    正在改进ing..........
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/4/14 16:59:00
     
     weiyi 美女呀,离线,快来找我吧!
      
      
      等级:大一新生
      文章:2
      积分:66
      门派:XML.ORG.CN
      注册:2005/3/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给weiyi发送一个短消息 把weiyi加入好友 查看weiyi的个人资料 搜索weiyi在『 SVG/GML/VRML/X3D/XAML 』的所有贴子 引用回复这个贴子 回复这个贴子 查看weiyi的博客3
    发贴心情 
    请问你有没有关于用JAVA生成svg饼图的例子:)
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/5/26 9:17:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 SVG/GML/VRML/X3D/XAML 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2025/2/27 21:32:29

    本主题贴数3,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    140.625ms