asp.net中用VML动态的画出数据分析图表详解_[Asp.Net教程]
					 在开发系统的时候有许多数据分析需要用图形的方式来表现出,这样更直观又清淅。如果我们使用高级去动态
生成统计图表的话不但编写起来非常困难,而且实用性不是很好,从美观的角度上讲也是很设计的。然而Microsoft公司提供了一个专们的矢量画图语言,这就是VML.
 如果要用VML去画静态页面的话那是比较好看也好操作,但实用性不是很高。但要是画出来的图所表示的数据
是从数据库里面读取下来的可以动态表示要统计的内容的话,那实用性就不言而喻了。
 最近我们也要做一个数据统计图表,我想如果能把VML画图做成一个控件那该多很,做自定义控件(本人才疏学浅)我不怎么会做,但我们公司有个.NET很牛 的人,我经常看到他重写.net里自带的控件使这些控件变得更好用,于是我也产生一种想法,看能不能把VML也嵌套进去.结果做的还是有点起色.下面跟大 家分享一下.
我是把VML图表用Lable控件显示出来的,给Lable类添加了一些自定义属性.(在下面的代码里面有的属性还没有用到用与以后扩展)
 页面代码如下
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="DrawTest.aspx.cs" Inherits="DrawTest" %>
 xmlns="http://www.w3.org/1999/xhtml">
 Page
 
 
本文由 设计家园  收集整理
这里面的.标签里的” xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"
”和. v\:*{ behavior: url(#default#VML) }
o\:*{ behavior: url(#default#VML) }
是必不可少的.
下面是CS代码部分
private int xposition;
 private int yposition;
 private int xwidth;
 private int yheight;
 private bool isdrawVML;
 private int bgdistance;//背景距离(斜线之间的垂直距离)
 private int zhuWidth;
 private string lineColor;
 private int yItemWidth;
 private string xSign;//X轴标记
 private string ySign;//Y轴标记
 private List datasource;
 private IszhuOrBing isZhuOrBing;
 private int radii;//画饼图要用的半径
 public IszhuOrBing IsZhuOrBing
 {
 get { return isZhuOrBing; }
 set { isZhuOrBing = value; }
 }
 #region 属性的定义
 
 /// 
 /// 画饼图的半径
 /// 
 public int Redii
 {
 get { return radii; }
 set { radii = value; }
 }
 /// 
 /// X轴的位置
 /// 
 public int XPosition
 {
 get { return xposition; }
 set { xposition = value; }
 }
 /// 
 /// Y轴位置
 /// 
 public int YPosition
 {
 get { return yposition; }
 set { yposition = value; }
 }
 //
 /// 
 /// X轴宽度
 /// 
 public int XWidth
 {
 get { return xwidth; }
 set { xwidth = value; }
 }
 //
 /// 
 /// Y轴高度
 /// 
 public int YHeight
 {
 get { return yheight; }
 set { yheight = value; }
 }
 /// 
 /// 是否是画VML图
 /// 
 public bool IsDrawVML
 {
 get { return isdrawVML; }
 set { isdrawVML = value; }
 }
 /// 
 /// 背景距离(斜线之间的垂直距离)
 /// 
 public int BgDistance
 {
 get
 {
 return bgdistance;
 }
 set
 {
 if (value <= 0)
 bgdistance = 10;
 else
 bgdistance = value;
 }
 }
 /// 
 /// 柱子的宽度
 /// 
 public int ZhuWidth
 {
 get { return zhuWidth; }
 set { zhuWidth = value; }
 }
 /// 
 /// 柱子的颜色
 /// 
 public string LineColor
 {
 get { return lineColor; }
 set { lineColor = value; }
 }
 
 /// 
 /// Y轴方向的间距
 /// 
 public int YItemWidth
 {
 get { return yItemWidth; }
 set { yItemWidth = value; }
 }
 /// 
 /// X轴标识
 /// 
 public string XSign
 {
 get { return xSign; }
 set { xSign = value; }
 }
 /// 
 /// Y轴标识
 /// 
 public string YSign
 {
 get { return ySign; }
 set { ySign = value; }
 }
 /// 
 /// 数据源(柱子高度)
 /// 
 public List DataSource
 {
 get { return datasource; }
 set { datasource = value; }
 }
 #endregion
判断是画柱图还是饼图.
 //画VML图
 StringBuilder sbText = new StringBuilder();
 string strHeight = "";
 string strTop = "";
 public void DrawVml()
 {
 if (isdrawVML == true)
 {//
 if (isZhuOrBing== IszhuOrBing.Bing)
 {
 DrawBingImage();
 }
 else if (isZhuOrBing == IszhuOrBing.Zhu)
 {
 DrawZhuImage();
 }
 }
 } 
***IsZhuOrBing是一个自定义的枚举类型.
 //柱子一升的脚本
 private string RegisterScript()
 {
 string m_strScript = " ";
 return m_strScript;
 }
上面的那段代码是要向客户端注册的JS脚本用于,画柱图时渐长效果的.
开始画VML图
//画柱图.
 public void DrawZhuImage()
 {
 base.Text = "";
 //画Div
 //sbText.Append("
");
 sbText.Append("
");
 //base.Style.Value = "left:" + xposition + ";position:relative; top:" + yposition + "; width:" + (xwidth+20) + "; height:" + (20+yheight) + ";'";
 //画X轴
 sbText.Append(""
 + "" + xSign + "");
 //画X轴方向的线条
 int HaveData = ComputeX(xwidth);
 //if (HaveData == 0)
 //{
 // sbText.Append("
");
 // base.Text = sbText.ToString(0, sbText.Length);
 // return;
 //}
 //画Y轴
 sbText.Append("" + ySign + "");
 //画Y轴方向的线条
 ComputeY(yheight);
 //画DIV结束标记
 sbText.Append("
");
 //画隐形文本框
 sbText.Append("");
 sbText.Append("");
 //给Lable控件的Text赋值
 base.Text = sbText.ToString(0, sbText.Length);
 Page.RegisterStartupScript("zhuup", RegisterScript());
 }
 //
 private int ComputeX(int XWidth)
 { //柱子颜色数组
 string[,] ZColor = new string[6, 2];
 ZColor[0, 0] = "#666699"; ZColor[0, 1] = "#d9d9e5";
 ZColor[1, 0] = "#00ff00"; ZColor[1, 1] = "#d1ffd1";
 ZColor[2, 0] = "#ff0000"; ZColor[2, 1] = "#ffbbbb";
 ZColor[3, 0] = "#ff9900"; ZColor[3, 1] = "#ffe3bb";
 ZColor[4, 0] = "#33cccc"; ZColor[4, 1] = "#cff4f3";
 ZColor[5, 0] = "#993300"; ZColor[5, 1] = "#ffc7ab";
 
 XWidth -= 10;//箭头下面的长度
 
 int ColorIndex = 0;
 double height = 0;
 int Zhuposition = 0;
 int Count = this.DataSource==null?XWidth:this.DataSource.Count;
 int num=1;
 //Count = 0;
 //if (Count == 0)
 //{
 // sbText.Append("
暂无数据
");
 // return 0;
 //}
 int UnitLength = XWidth / Count;//计算单位长度
 foreach (VmlDataSource var in this.datasource)
 {
 //画X轴下标
 sbText.Append(""
 + "" + var.Key + "");
 height = var.value;
 Zhuposition = ((num - 1) * UnitLength + UnitLength / 2) - (zhuWidth / 2);
 if (ColorIndex >= ZColor.Length / 2)
 {
 ColorIndex = 0;
 }
 //sbText.Append(""
 + ""
 + ""
 + "" + height + "");
 strHeight += height + ",";
 strTop += (yheight - height) + ",";
 ColorIndex++; 
 num++;
 }
 return 1;
 }
 //
 private void ComputeY(int YHeight)
 {
 YHeight -= 10;//箭头下面的长度
 if (yItemWidth > 0)
 {
 int Units = YHeight / yItemWidth;//计算单位长度
 for (int i = 0; i <= Units; i++)
 {
 int areaLenght = yheight - (i * yItemWidth);
 sbText.Append(""
 + ""
 + "" + i * yItemWidth + ""
 + "");
 }
 //画Y轴平行的线
 sbText.Append("");
 }
 }
 #endregion
 #region 画饼图
 private void DrawBingImage()
 {
 base.Text = "";
 //定义颜色
 string[] Colors = new string[6];
 Colors[0] = "#666699";
 Colors[1] = "#00ff00";
 Colors[2] = "#ff0000";
 Colors[3] = "#ff9900";
 Colors[4] = "#33cccc";
 Colors[5] = "#993300"; 
 //开始标记
 //sbText.Append("
");
 //
 double TotalCount = 0;
 foreach (VmlDataSource vd in datasource)
 {
 TotalCount += vd.value;
 }
 //计算单位数字的角度
 double UnitAngle = 360 / TotalCount;
 //存储画下弧度的起点
 double TempUnitArc=0.00;
 //存储前面已有的角度
 double TempUnitAngle=0.00;
 int i = 0;
 string ColorInfo = "";
 sbText.Append("
");
 sbText.Append("
");
 sbText.Append("");
 foreach (VmlDataSource vd in datasource)
 {
 //计算弧度
 double UnitArc = (vd.value * UnitAngle + TempUnitAngle) * Math.PI / 180;
 //计算开始和结束位置
 double sx = Math.Round(Math.Cos(TempUnitArc) * radii);//Math.Sign(
 double sy = Math.Round(Math.Sin(TempUnitArc) * radii);
 double ex = Math.Round(Math.Cos(UnitArc) * radii);
 //double aa = Math.Sin(UnitArc) * radii;
 //double bb = Math.Round(Math.Sin(UnitArc) * radii,4);
 double ey = Math.Round(Math.Sin(UnitArc) * radii);
 //所占百份比
 double rate = Math.Round(vd.value * 100 / TotalCount, 2);
 //开始画图
 sbText.Append(" sbText.Append(" path='m0,0 l" + sx + "," + sy + " ar-" + radii + ",-" + radii + "," + radii + "," + radii + "," + ex + "," + ey + "," + sx + "," + sy + " l0,0 x e'");
 sbText.Append("title='名称:" + vd.key + "\r数量:" + vd.value + "\r所占比例:" + rate + "%'>");
 //给临时变量赋值
 TempUnitAngle += vd.value * UnitAngle;
 TempUnitArc = UnitArc;
 //显示颜色说明框
 ColorInfo += "
onMouseOver='this.style.border=\"solid 1px #D38F61\"' onMouseOut='this.style.border=\"none\"'>"
 + " " + vd.key + ":" + vd.value + " (" + rate + "%)
"
 ;
 //如果颜色遍历完了,还有数据要显示那就重新再一次遍历。占:" + (Math.Round(vd.value * 100 / TotalCount, 2)) + "%
 i = (i >= Colors.Length ? 0 : ++i);
 }
 sbText.Append("
");
 sbText.Append("
");
 //sbText.Append("
");
 //总数
 sbText.Append("
总数据:"+TotalCount+"
");
 sbText.Append(ColorInfo);
 sbText.Append("
");
 this.Text = sbText.ToString();
 }
 #endregion
 /// 
 /// 控件加载时画图
 /// 
 /// 
 protected override void OnLoad(EventArgs e)
 {
 base.OnLoad(e); // Page.RegisterStartupScript("HelloWord", "");
 DrawVml();
 //Page.RegisterStartupScript("", "");
 }
 protected override void OnPreRender(EventArgs e)
 {
 base.OnPreRender(e);
 Page.RegisterStartupScript("", "");
 }
 }
*注意里面的数据源类型和枚举在下面定义.
 /// 
 /// 画图时用的数据源
 /// 
 public class VmlDataSource
 {
 public VmlDataSource()
 {
 }
 public string key;
 public double value;
 /// 
 /// 键值
 /// 
 public string Key
 {
 get { return key; }
 set { key = value; }
 }
 public double Value
 {
 get
 {
 if (this.value.GetType() != Type.GetType("System.Int32"))
 return 0;
 else
 return this.value;
 }
 set
 {
 this.value = value;
 }
 }
 }
 /// 
 /// 枚举画图的类型
 /// 
 public enum IszhuOrBing
 {
 //
 Zhu=0,
 //
 Bing=1
 }
}
整个过程就是这样了,不过这只是个粗略的过程里面还很多的BUG没有解觉掉.画数据统计的图表完成了.
效果图如下.
本文由 设计家园  收集整理

饼图为:

本文由 设计家园  收集整理