在开发系统的时候有许多数据分析需要用图形的方式来表现出,这样更直观又清淅。如果我们使用高级去动态
生成统计图表的话不但编写起来非常困难,而且实用性不是很好,从美观的角度上讲也是很设计的。然而Microsoft公司提供了一个专们的矢量画图语言,这就是VML.
如果要用VML去画静态页面的话那是比较好看也好操作,但实用性不是很高。但要是画出来的图所表示的数据
是从数据库里面读取下来的可以动态表示要统计的内容的话,那实用性就不言而喻了。
最近我们也要做一个数据统计图表,我想如果能把VML画图做成一个控件那该多很,做自定义控件(本人才疏学浅)我不怎么会做,但我们公司有个.NET很牛 的人,我经常看到他重写.net里自带的控件使这些控件变得更好用,于是我也产生一种想法,看能不能把VML也嵌套进去.结果做的还是有点起色.下面跟大 家分享一下.
我是把VML图表用Lable控件显示出来的,给Lable类添加了一些自定义属性.(在下面的代码里面有的属性还没有用到用与以后扩展)
页面代码如下<%@ Page Language="C#" AutoEventWireup="true" CodeFile="DrawTest.aspx.cs" Inherits="DrawTest" %>
<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Page</title>
<style type="text/css">
v\:*{ behavior: url(#default#VML) }
o\:*{ behavior: url(#default#VML) }
.changeBg{FILTER: progid:DXImageTransform.Microsoft.Gradient(gradientType=0,startColorStr=#FFFFFF,endColorStr=#9DCDFA);
}
.shadwDiv{ width:600px; height:500px; text-align:center; filter : progid:DXImageTransform.Microsoft.DropShadow ( enabled=true , color=#000 , offX=10 , offY=10 , positive=true ) ; }
</style>
</head>
<body>
<form id="form1" runat="server">
<div class="shadwDiv" >
<div style="padding-top: 30px; border: solid 2px #BBBBBB; background-color: #EFEFEF;
width: 600px; height: 500px;">
<asp:VmlLabel ID="labTest3" runat="server" XWidth="400" YHeight="400" YPosition="50"
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"></asp:VmlLabel>
</div>
</div>
</form>
</body>
</html>
<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Page</title>
<style type="text/css">
v\:*{ behavior: url(#default#VML) }
o\:*{ behavior: url(#default#VML) }
.changeBg{FILTER: progid:DXImageTransform.Microsoft.Gradient(gradientType=0,startColorStr=#FFFFFF,endColorStr=#9DCDFA);
}
.shadwDiv{ width:600px; height:500px; text-align:center; filter : progid:DXImageTransform.Microsoft.DropShadow ( enabled=true , color=#000 , offX=10 , offY=10 , positive=true ) ; }
</style>
</head>
<body>
<form id="form1" runat="server">
<div class="shadwDiv" >
<div style="padding-top: 30px; border: solid 2px #BBBBBB; background-color: #EFEFEF;
width: 600px; height: 500px;">
<asp:VmlLabel ID="labTest3" runat="server" XWidth="400" YHeight="400" YPosition="50"
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"></asp:VmlLabel>
</div>
</div>
</form>
</body>
</html>
这里面的.<html>标签里的” 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<VmlDataSource> datasource;
private IszhuOrBing isZhuOrBing;
private int radii;//画饼图要用的半径
public IszhuOrBing IsZhuOrBing
{
get { return isZhuOrBing; }
set { isZhuOrBing = value; }
}
#region 属性的定义
/// <summary>
/// 画饼图的半径
/// </summary>
public int Redii
{
get { return radii; }
set { radii = value; }
}
/// <summary>
/// X轴的位置
/// </summary>
public int XPosition
{
get { return xposition; }
set { xposition = value; }
}
/// <summary>
/// Y轴位置
/// </summary>
public int YPosition
{
get { return yposition; }
set { yposition = value; }
}
//
/// <summary>
/// X轴宽度
/// </summary>
public int XWidth
{
get { return xwidth; }
set { xwidth = value; }
}
//
/// <summary>
/// Y轴高度
/// </summary>
public int YHeight
{
get { return yheight; }
set { yheight = value; }
}
/// <summary>
/// 是否是画VML图
/// </summary>
public bool IsDrawVML
{
get { return isdrawVML; }
set { isdrawVML = value; }
}
/// <summary>
/// 背景距离(斜线之间的垂直距离)
/// </summary>
public int BgDistance
{
get
{
return bgdistance;
}
set
{
if (value <= 0)
bgdistance = 10;
else
bgdistance = value;
}
}
/// <summary>
/// 柱子的宽度
/// </summary>
public int ZhuWidth
{
get { return zhuWidth; }
set { zhuWidth = value; }
}
/// <summary>
/// 柱子的颜色
/// </summary>
public string LineColor
{
get { return lineColor; }
set { lineColor = value; }
}
/// <summary>
/// Y轴方向的间距
/// </summary>
public int YItemWidth
{
get { return yItemWidth; }
set { yItemWidth = value; }
}
/// <summary>
/// X轴标识
/// </summary>
public string XSign
{
get { return xSign; }
set { xSign = value; }
}
/// <summary>
/// Y轴标识
/// </summary>
public string YSign
{
get { return ySign; }
set { ySign = value; }
}
/// <summary>
/// 数据源(柱子高度)
/// </summary>
public List<VmlDataSource> 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 = " <script language='javascript' type='text/javascript'>"
+"var gao=0;"
+"var ProcID=0;"
+"var ProcName=null;"
+"var i=0;"
+"var HeightContent=document.getElementById('heightDataSource').value;"
+"var arrHeight=new Array();"
+"var arrTop=new Array();"
+"arrHeight=HeightContent.split(',');"
+"var showBar=null;"
+"function AllPlay()"
+"{"
+" i++;"
+" gao=0;"
+" var procBarID='DataZhu'+i;"//;
+" Play(procBarID); "
+"}"
+"function Play(procBarID)"
+"{ "
+" var procBar=document.getElementById(procBarID);"
+" if(procBar!=null)"
+" {"
+" ProcName=procBar;"
+" PlaySub();"
+"}"
+"}"
+"function PlaySub()"
+"{"
+" var procBar=ProcName;"
+" showBar=document.getElementById('ShowData'+i);"
+" showBar.style.display='block';"
+"gao++;"
+"var ygao=parseInt(procBar.style.height);"
+"var ytop=parseInt(procBar.style.top);"
+"if(ygao<arrHeight[i-1])"
+"{ "
+" procBar.style.top=ytop-gao;"
+" procBar.style.height=ygao+gao;"
+" showBar.style.top=ytop-gao-25;"
+"setTimeout(PlaySub,20);"
+"}"
+"else"
+"{ "
+" AllPlay();"
+"}"
+"}"
+"</script>";
return m_strScript;
}
上面的那段代码是要向客户端注册的JS脚本用于,画柱图时渐长效果的.
开始画VML图
//画柱图.
public void DrawZhuImage()
{
base.Text = "";
//画Div
//sbText.Append("<div style=' border:solid 1px red;width:" + (xwidth+10) + "; height:" + (yheight+10) + ";;filter : progid:DXImageTransform.Microsoft.DropShadow ( enabled=true , color=#66333333 , offX=4 , offY=4 , positive=true );'>");
sbText.Append("<div id='PicDiv' style='left:0;position:relative; top:0; width:" + xwidth + "; height:" + yheight + ";text-align:left;'>");
//base.Style.Value = "left:" + xposition + ";position:relative; top:" + yposition + "; width:" + (xwidth+20) + "; height:" + (20+yheight) + ";'";
//画X轴
sbText.Append("<v:line id='Xzhou' from='0," + yheight + "' to='" + xwidth + "," + yheight + "'>"
+ "<v:stroke EndArrow='Classic'/></v:line><v:TextBox style='position:absolute; width:100px;top:" + (yheight + 10) + ";left:" + (xwidth) + "'>" + xSign + "</v:TextBox>");
//画X轴方向的线条
int HaveData = ComputeX(xwidth);
//if (HaveData == 0)
//{
// sbText.Append("</div>");
// base.Text = sbText.ToString(0, sbText.Length);
// return;
//}
//画Y轴
sbText.Append("<v:line id='Yzhou' from='0," + yheight + "' to='0,0'><v:stroke EndArrow='Classic'/><v:TextBox style=' width:100px;padding-left:10px;'>" + ySign + "</v:TextBox></v:line>");
//画Y轴方向的线条
ComputeY(yheight);
//画DIV结束标记
sbText.Append("</div>");
//画隐形文本框
sbText.Append("<input type='hidden' value='" + strHeight.Substring(0, strHeight.Length - 1) + "' name='heightDataSource' id='heightDataSource'/>");
sbText.Append("<input type='hidden' value='" + strTop.Substring(0, strTop.Length - 1) + "' name='topDataSource' id='topDataSource'/>");
//给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("<div style='font-size:14px;color:red;'>暂无数据</div>");
// return 0;
//}
int UnitLength = XWidth / Count;//计算单位长度
foreach (VmlDataSource var in this.datasource)
{
//画X轴下标
sbText.Append("<v:line from='" + num * UnitLength + "," + yheight + "' to='" + num * UnitLength + "," + (yheight + bgdistance) + "'>"
+ "</v:line><v:shape style='left:" + (num * UnitLength -50) + ";top:" + yheight + ";'><v:textbox>" + var.Key + "</v:textbox></v:shape>");
height = var.value;
Zhuposition = ((num - 1) * UnitLength + UnitLength / 2) - (zhuWidth / 2);
if (ColorIndex >= ZColor.Length / 2)
{
ColorIndex = 0;
}
//sbText.Append("<v:rect id='DataZhu"+num+"' style='z-index:1; position:absolute; top:" + (yheight - height) + ";"
sbText.Append("<v:rect id='DataZhu"+num+"' style='z-index:1; position:absolute; top:" + yheight + ";"
+ "left:" + Zhuposition + ";width:" + zhuWidth + ";height:0;' fillcolor='" + ZColor[ColorIndex, 0] + "'>"
+ "<v:fill color2='" + ZColor[ColorIndex, 1] + "' rotate='t' type='gradient'/>"
+ "<v:extrusion v:ext='view' backdepth='" + (2 * bgdistance) + "' color='" + ZColor[ColorIndex, 0] + "' brightness='0.2' on='t'/></v:rect>"
+ "<v:TextBox id='ShowData"+num+"' style='position:absolute;display:none;z-index:2;top:" + (yheight - 20) + "; left:" + Zhuposition + "'>" + height + "</v:TextBox>");
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("<v:line from='0," + areaLenght + "' to='" + bgdistance + "," + (areaLenght - bgdistance) + "' color='" + lineColor + "'><v:stroke color='" + lineColor + "'/></v:line>"
+ "<v:line from='0," + areaLenght + "' to='-10," + areaLenght + "'>"
+ "</v:line><v:shape style='top:" + (areaLenght-10) + ";left:-50;'><v:TextBox>" + i * yItemWidth + "</v:TextBox></v:shape>"
+ "<v:line from='" + bgdistance + "," + (areaLenght - bgdistance) + "' to='" + xwidth + "," + (areaLenght - bgdistance) + "'><v:stroke color='" + lineColor + "'/></v:line>");
}
//画Y轴平行的线
sbText.Append("<v:line id='YzhouPX' from='" + bgdistance + "," + (yheight - bgdistance) + "' to='" + bgdistance + "," + ((yheight - (Units * yItemWidth)) - bgdistance) + "'><v:stroke color='" + lineColor + "'/></v:line>");
}
}
#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("<div id='pic' style='position:absolute;'>");
//
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("<div id='PicDiv' style='left:0;position:relative; top:0; width:" + xwidth + "; height:" + yheight + ";text-align:left; font-size:12px; border:solid 1px red;'>");
sbText.Append("<div style='left:" + (radii+xposition) + ";position:relative; top:" + (radii+yposition) + ";'>");
sbText.Append("<v:TextBox id='msgShow' inset='5pt,5pt,5pt,5pt' style='width:" + Colors[i] + ";position:absolute;z-index:2;display:none;background-color:red; font-size:12px;'></v:TextBox>");
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("<v:shape ID='ccc' style='position:absolute;width:200px; height:200px;'coordsize='200,200' fillcolor='#" + Colors[i] + "' filled='t' strokecolor='#FFFFFF'");
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 + "%'></v:shape>");
//给临时变量赋值
TempUnitAngle += vd.value * UnitAngle;
TempUnitArc = UnitArc;
//显示颜色说明框
ColorInfo += "<div style='position:relative;padding-top:3px;padding-bottom:3px;' title='所占比例:" + rate + "%' onMouseOver='this.style.border=\"solid 1px #D38F61\"' onMouseOut='this.style.border=\"none\"'>"
+ " <v:rect style='position:relative;width:20px;height:20px;' fillcolor='" + Colors[i] + "'/>" + vd.key + ":" + vd.value + " (" + rate + "%)</div>"
;
//如果颜色遍历完了,还有数据要显示那就重新再一次遍历。占:" + (Math.Round(vd.value * 100 / TotalCount, 2)) + "%
i = (i >= Colors.Length ? 0 : ++i);
}
sbText.Append("</div>");
sbText.Append("<div style='border:solid 1px #000;padding:10px;margin-right:10px;position:relative;left:" + (2 * radii + 20 + xposition) + "px;top:10px;width:" + (xwidth - (2 * radii + 40 + xposition)) + ";'>");
//sbText.Append("<div style='padding-left:10px;width:" + (xwidth - (2 * radii +30+ xposition)) +";height:auto;'>");
//总数
sbText.Append("<div style='background-color:#000;color:#fff;'>总数据:"+TotalCount+"</div>");
sbText.Append(ColorInfo);
sbText.Append("</div></div>");
this.Text = sbText.ToString();
}
#endregion
/// <summary>
/// 控件加载时画图
/// </summary>
/// <param name="e"></param>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e); // Page.RegisterStartupScript("HelloWord", "<script>alert('BBB');</script>");
DrawVml();
//Page.RegisterStartupScript("", "<script>alert('aaa');</script>");
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
Page.RegisterStartupScript("", "<script>AllPlay();</script>");
}
}
*注意里面的数据源类型和枚举在下面定义.
/// <summary>
/// 画图时用的数据源
/// </summary>
public class VmlDataSource
{
public VmlDataSource()
{
}
public string key;
public double value;
/// <summary>
/// 键值
/// </summary>
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;
}
}
}
/// <summary>
/// 枚举画图的类型
/// </summary>
public enum IszhuOrBing
{
//
Zhu=0,
//
Bing=1
}
}
整个过程就是这样了,不过这只是个粗略的过程里面还很多的BUG没有解觉掉.画数据统计的图表完成了.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<VmlDataSource> datasource;
private IszhuOrBing isZhuOrBing;
private int radii;//画饼图要用的半径
public IszhuOrBing IsZhuOrBing
{
get { return isZhuOrBing; }
set { isZhuOrBing = value; }
}
#region 属性的定义
/// <summary>
/// 画饼图的半径
/// </summary>
public int Redii
{
get { return radii; }
set { radii = value; }
}
/// <summary>
/// X轴的位置
/// </summary>
public int XPosition
{
get { return xposition; }
set { xposition = value; }
}
/// <summary>
/// Y轴位置
/// </summary>
public int YPosition
{
get { return yposition; }
set { yposition = value; }
}
//
/// <summary>
/// X轴宽度
/// </summary>
public int XWidth
{
get { return xwidth; }
set { xwidth = value; }
}
//
/// <summary>
/// Y轴高度
/// </summary>
public int YHeight
{
get { return yheight; }
set { yheight = value; }
}
/// <summary>
/// 是否是画VML图
/// </summary>
public bool IsDrawVML
{
get { return isdrawVML; }
set { isdrawVML = value; }
}
/// <summary>
/// 背景距离(斜线之间的垂直距离)
/// </summary>
public int BgDistance
{
get
{
return bgdistance;
}
set
{
if (value <= 0)
bgdistance = 10;
else
bgdistance = value;
}
}
/// <summary>
/// 柱子的宽度
/// </summary>
public int ZhuWidth
{
get { return zhuWidth; }
set { zhuWidth = value; }
}
/// <summary>
/// 柱子的颜色
/// </summary>
public string LineColor
{
get { return lineColor; }
set { lineColor = value; }
}
/// <summary>
/// Y轴方向的间距
/// </summary>
public int YItemWidth
{
get { return yItemWidth; }
set { yItemWidth = value; }
}
/// <summary>
/// X轴标识
/// </summary>
public string XSign
{
get { return xSign; }
set { xSign = value; }
}
/// <summary>
/// Y轴标识
/// </summary>
public string YSign
{
get { return ySign; }
set { ySign = value; }
}
/// <summary>
/// 数据源(柱子高度)
/// </summary>
public List<VmlDataSource> 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 = " <script language='javascript' type='text/javascript'>"
+"var gao=0;"
+"var ProcID=0;"
+"var ProcName=null;"
+"var i=0;"
+"var HeightContent=document.getElementById('heightDataSource').value;"
+"var arrHeight=new Array();"
+"var arrTop=new Array();"
+"arrHeight=HeightContent.split(',');"
+"var showBar=null;"
+"function AllPlay()"
+"{"
+" i++;"
+" gao=0;"
+" var procBarID='DataZhu'+i;"//;
+" Play(procBarID); "
+"}"
+"function Play(procBarID)"
+"{ "
+" var procBar=document.getElementById(procBarID);"
+" if(procBar!=null)"
+" {"
+" ProcName=procBar;"
+" PlaySub();"
+"}"
+"}"
+"function PlaySub()"
+"{"
+" var procBar=ProcName;"
+" showBar=document.getElementById('ShowData'+i);"
+" showBar.style.display='block';"
+"gao++;"
+"var ygao=parseInt(procBar.style.height);"
+"var ytop=parseInt(procBar.style.top);"
+"if(ygao<arrHeight[i-1])"
+"{ "
+" procBar.style.top=ytop-gao;"
+" procBar.style.height=ygao+gao;"
+" showBar.style.top=ytop-gao-25;"
+"setTimeout(PlaySub,20);"
+"}"
+"else"
+"{ "
+" AllPlay();"
+"}"
+"}"
+"</script>";
return m_strScript;
}
上面的那段代码是要向客户端注册的JS脚本用于,画柱图时渐长效果的.
开始画VML图
//画柱图.
public void DrawZhuImage()
{
base.Text = "";
//画Div
//sbText.Append("<div style=' border:solid 1px red;width:" + (xwidth+10) + "; height:" + (yheight+10) + ";;filter : progid:DXImageTransform.Microsoft.DropShadow ( enabled=true , color=#66333333 , offX=4 , offY=4 , positive=true );'>");
sbText.Append("<div id='PicDiv' style='left:0;position:relative; top:0; width:" + xwidth + "; height:" + yheight + ";text-align:left;'>");
//base.Style.Value = "left:" + xposition + ";position:relative; top:" + yposition + "; width:" + (xwidth+20) + "; height:" + (20+yheight) + ";'";
//画X轴
sbText.Append("<v:line id='Xzhou' from='0," + yheight + "' to='" + xwidth + "," + yheight + "'>"
+ "<v:stroke EndArrow='Classic'/></v:line><v:TextBox style='position:absolute; width:100px;top:" + (yheight + 10) + ";left:" + (xwidth) + "'>" + xSign + "</v:TextBox>");
//画X轴方向的线条
int HaveData = ComputeX(xwidth);
//if (HaveData == 0)
//{
// sbText.Append("</div>");
// base.Text = sbText.ToString(0, sbText.Length);
// return;
//}
//画Y轴
sbText.Append("<v:line id='Yzhou' from='0," + yheight + "' to='0,0'><v:stroke EndArrow='Classic'/><v:TextBox style=' width:100px;padding-left:10px;'>" + ySign + "</v:TextBox></v:line>");
//画Y轴方向的线条
ComputeY(yheight);
//画DIV结束标记
sbText.Append("</div>");
//画隐形文本框
sbText.Append("<input type='hidden' value='" + strHeight.Substring(0, strHeight.Length - 1) + "' name='heightDataSource' id='heightDataSource'/>");
sbText.Append("<input type='hidden' value='" + strTop.Substring(0, strTop.Length - 1) + "' name='topDataSource' id='topDataSource'/>");
//给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("<div style='font-size:14px;color:red;'>暂无数据</div>");
// return 0;
//}
int UnitLength = XWidth / Count;//计算单位长度
foreach (VmlDataSource var in this.datasource)
{
//画X轴下标
sbText.Append("<v:line from='" + num * UnitLength + "," + yheight + "' to='" + num * UnitLength + "," + (yheight + bgdistance) + "'>"
+ "</v:line><v:shape style='left:" + (num * UnitLength -50) + ";top:" + yheight + ";'><v:textbox>" + var.Key + "</v:textbox></v:shape>");
height = var.value;
Zhuposition = ((num - 1) * UnitLength + UnitLength / 2) - (zhuWidth / 2);
if (ColorIndex >= ZColor.Length / 2)
{
ColorIndex = 0;
}
//sbText.Append("<v:rect id='DataZhu"+num+"' style='z-index:1; position:absolute; top:" + (yheight - height) + ";"
sbText.Append("<v:rect id='DataZhu"+num+"' style='z-index:1; position:absolute; top:" + yheight + ";"
+ "left:" + Zhuposition + ";width:" + zhuWidth + ";height:0;' fillcolor='" + ZColor[ColorIndex, 0] + "'>"
+ "<v:fill color2='" + ZColor[ColorIndex, 1] + "' rotate='t' type='gradient'/>"
+ "<v:extrusion v:ext='view' backdepth='" + (2 * bgdistance) + "' color='" + ZColor[ColorIndex, 0] + "' brightness='0.2' on='t'/></v:rect>"
+ "<v:TextBox id='ShowData"+num+"' style='position:absolute;display:none;z-index:2;top:" + (yheight - 20) + "; left:" + Zhuposition + "'>" + height + "</v:TextBox>");
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("<v:line from='0," + areaLenght + "' to='" + bgdistance + "," + (areaLenght - bgdistance) + "' color='" + lineColor + "'><v:stroke color='" + lineColor + "'/></v:line>"
+ "<v:line from='0," + areaLenght + "' to='-10," + areaLenght + "'>"
+ "</v:line><v:shape style='top:" + (areaLenght-10) + ";left:-50;'><v:TextBox>" + i * yItemWidth + "</v:TextBox></v:shape>"
+ "<v:line from='" + bgdistance + "," + (areaLenght - bgdistance) + "' to='" + xwidth + "," + (areaLenght - bgdistance) + "'><v:stroke color='" + lineColor + "'/></v:line>");
}
//画Y轴平行的线
sbText.Append("<v:line id='YzhouPX' from='" + bgdistance + "," + (yheight - bgdistance) + "' to='" + bgdistance + "," + ((yheight - (Units * yItemWidth)) - bgdistance) + "'><v:stroke color='" + lineColor + "'/></v:line>");
}
}
#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("<div id='pic' style='position:absolute;'>");
//
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("<div id='PicDiv' style='left:0;position:relative; top:0; width:" + xwidth + "; height:" + yheight + ";text-align:left; font-size:12px; border:solid 1px red;'>");
sbText.Append("<div style='left:" + (radii+xposition) + ";position:relative; top:" + (radii+yposition) + ";'>");
sbText.Append("<v:TextBox id='msgShow' inset='5pt,5pt,5pt,5pt' style='width:" + Colors[i] + ";position:absolute;z-index:2;display:none;background-color:red; font-size:12px;'></v:TextBox>");
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("<v:shape ID='ccc' style='position:absolute;width:200px; height:200px;'coordsize='200,200' fillcolor='#" + Colors[i] + "' filled='t' strokecolor='#FFFFFF'");
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 + "%'></v:shape>");
//给临时变量赋值
TempUnitAngle += vd.value * UnitAngle;
TempUnitArc = UnitArc;
//显示颜色说明框
ColorInfo += "<div style='position:relative;padding-top:3px;padding-bottom:3px;' title='所占比例:" + rate + "%' onMouseOver='this.style.border=\"solid 1px #D38F61\"' onMouseOut='this.style.border=\"none\"'>"
+ " <v:rect style='position:relative;width:20px;height:20px;' fillcolor='" + Colors[i] + "'/>" + vd.key + ":" + vd.value + " (" + rate + "%)</div>"
;
//如果颜色遍历完了,还有数据要显示那就重新再一次遍历。占:" + (Math.Round(vd.value * 100 / TotalCount, 2)) + "%
i = (i >= Colors.Length ? 0 : ++i);
}
sbText.Append("</div>");
sbText.Append("<div style='border:solid 1px #000;padding:10px;margin-right:10px;position:relative;left:" + (2 * radii + 20 + xposition) + "px;top:10px;width:" + (xwidth - (2 * radii + 40 + xposition)) + ";'>");
//sbText.Append("<div style='padding-left:10px;width:" + (xwidth - (2 * radii +30+ xposition)) +";height:auto;'>");
//总数
sbText.Append("<div style='background-color:#000;color:#fff;'>总数据:"+TotalCount+"</div>");
sbText.Append(ColorInfo);
sbText.Append("</div></div>");
this.Text = sbText.ToString();
}
#endregion
/// <summary>
/// 控件加载时画图
/// </summary>
/// <param name="e"></param>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e); // Page.RegisterStartupScript("HelloWord", "<script>alert('BBB');</script>");
DrawVml();
//Page.RegisterStartupScript("", "<script>alert('aaa');</script>");
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
Page.RegisterStartupScript("", "<script>AllPlay();</script>");
}
}
*注意里面的数据源类型和枚举在下面定义.
/// <summary>
/// 画图时用的数据源
/// </summary>
public class VmlDataSource
{
public VmlDataSource()
{
}
public string key;
public double value;
/// <summary>
/// 键值
/// </summary>
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;
}
}
}
/// <summary>
/// 枚举画图的类型
/// </summary>
public enum IszhuOrBing
{
//
Zhu=0,
//
Bing=1
}
}
效果图如下.
饼图为: