Go homepage(回首页) Upload pictures (上传图片) Write articles (发文字帖)
The author:(作者)delvpublished in(发表于) 1/27/2014 6:48:04 AM 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
IsDrawVML="True" BgDistance="10" EnableViewState="False" ZhuWidth="20" YItemWidth="40" CssClass="changeBg" BorderColor="White" BorderWidth="0px" LineColor="#4CAFFE" XSign="(年份)" YSign="(万/单位)" XPosition="50" IsZhuOrBing="Zhu" Redii="80"> 本文由 设计家园 收集整理
这里面的.标签里的” 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 + "");
//画DIV结束标记 sbText.Append("
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没有解觉掉.画数据统计的图表完成了.效果图如下.本文由 设计家园 收集整理饼图为:本文由 设计家园 收集整理 赞 If you have any requirements, please contact webmaster。(如果有什么要求,请联系站长) QQ:154298438 QQ:417480759
//计算弧度 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("
}
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没有解觉掉.画数据统计的图表完成了.效果图如下.本文由 设计家园 收集整理饼图为:本文由 设计家园 收集整理
赞