用ASP.NET with C#绘制柱状图(Bar图)
昨天发了个绘制Curve图的,自古Curve图,Bar图,Pie图都不分家,今天就继续来绘制Bar图吧。照例图片拥有简单的缩放功能,来看看最终效果图:
其实绘制Bar图比绘制Curve图更简单,只需要绘制相应比例的方块即可,来看看初始化函数InitializeGraph()吧:
//初始化和填充图像区域,画出边框,初始标题
private void InitializeGraph()
{
//根据给定的高度和宽度创建一个位图图像
objBitmap = new Bitmap(Width,Height);
//从指定的 objBitmap 对象创建 objGraphics 对象 (即在objBitmap对象中画图)
objGraphics = Graphics.FromImage(objBitmap);
//根据给定颜色(LightGray)填充图像的矩形区域 (背景)
objGraphics.DrawRectangle(new Pen(BorderColor,1),0,0,Width,Height);
objGraphics.FillRectangle(new SolidBrush(BgColor),1,1,Width-2,Height-2);
//初始化标题
CreateTitle(ref objGraphics);
}
private void InitializeGraph()
{
//根据给定的高度和宽度创建一个位图图像
objBitmap = new Bitmap(Width,Height);
//从指定的 objBitmap 对象创建 objGraphics 对象 (即在objBitmap对象中画图)
objGraphics = Graphics.FromImage(objBitmap);
//根据给定颜色(LightGray)填充图像的矩形区域 (背景)
objGraphics.DrawRectangle(new Pen(BorderColor,1),0,0,Width,Height);
objGraphics.FillRectangle(new SolidBrush(BgColor),1,1,Width-2,Height-2);
//初始化标题
CreateTitle(ref objGraphics);
}
相对Curve图是不是简单了好多?不用绘制麻烦的X轴Y轴,之需要填充一个简单的背景即可。爽吧?
呵呵,初始化标题:
private void CreateTitle(ref Graphics objGraphics)
{
objGraphics.DrawString(Title,new Font("宋体",16),new SolidBrush(TextColor),new Point(5,5));
}
{
objGraphics.DrawString(Title,new Font("宋体",16),new SolidBrush(TextColor),new Point(5,5));
}
这时候生成的是一幅只有左上角有标题的空图片,我就不贴图了,下边绘制右上角的说明文字和相应的颜色表示方块:
//初始化右边说明部分
private void DrawRight(ref Graphics objGraphics)
{
objGraphics.DrawString(String.Format("单位:{0}",Unit),new Font("宋体",10),new SolidBrush(TextColor),Width-100,30);
Point KeysPoint = new Point(Width-95,50);
Point KeysTextPoint = new Point(Width-70,50);
for(int i=0;i < Keys.Length;i++)
{
objGraphics.DrawRectangle(new Pen(BorderColor,1),KeysPoint.X,KeysPoint.Y,21,11);
objGraphics.FillRectangle(new SolidBrush(GetColor(i)),KeysPoint.X,KeysPoint.Y,20,10);
objGraphics.DrawString(Keys[i],new Font("宋体",10),new SolidBrush(TextColor),KeysTextPoint);
KeysPoint.Y +=15;
KeysTextPoint.Y += 15;
}
}
private void DrawRight(ref Graphics objGraphics)
{
objGraphics.DrawString(String.Format("单位:{0}",Unit),new Font("宋体",10),new SolidBrush(TextColor),Width-100,30);
Point KeysPoint = new Point(Width-95,50);
Point KeysTextPoint = new Point(Width-70,50);
for(int i=0;i < Keys.Length;i++)
{
objGraphics.DrawRectangle(new Pen(BorderColor,1),KeysPoint.X,KeysPoint.Y,21,11);
objGraphics.FillRectangle(new SolidBrush(GetColor(i)),KeysPoint.X,KeysPoint.Y,20,10);
objGraphics.DrawString(Keys[i],new Font("宋体",10),new SolidBrush(TextColor),KeysTextPoint);
KeysPoint.Y +=15;
KeysTextPoint.Y += 15;
}
}
这时候图片除了具体的“柱子”外已经初始化完毕了:
如下:
剩下只是绘制相应的“柱子”了,因为“柱子”要适应图片的大小自动放大缩小,所以这里要费些周章,先要找出数据中最大值,然后以该最大值的“柱子”绘制适应图片的最高的“柱子”,然后其他按照比例照着绘制就可以了,先找出最大值吧:
//获取数组的最大值
private float MaxValues(float[] Values)
{
float MaxValue = Values[0];
for(int i = 0;i < Values.Length;i++)
{
if(Values[i] > MaxValue)
{
MaxValue = Values[i];
}
}
return MaxValue;
}
private float MaxValues(float[] Values)
{
float MaxValue = Values[0];
for(int i = 0;i < Values.Length;i++)
{
if(Values[i] > MaxValue)
{
MaxValue = Values[i];
}
}
return MaxValue;
}
万事俱备了,我们开始最后一步吧!
//Bar图的主要部分
private void DrawContent(ref Graphics objGraphics)
{
Point KeysPoint = new Point(20,Height - 20);
Point KeysTextPoint = new Point(20,Height - 20);
int SpaceWidth = (Width-120)/(Values.Length*2);
float SpaceHeight;
//画Bar
for(int i=0;i < Values.Length;i++)
{
SpaceHeight = (Height-100)*(Values[i]/MaxValues(Values));
objGraphics.DrawRectangle(new Pen(BorderColor,1),KeysPoint.X,KeysPoint.Y - SpaceHeight,SpaceWidth+1,SpaceHeight+1);
objGraphics.FillRectangle(new SolidBrush(GetColor(i)),KeysPoint.X,KeysPoint.Y - SpaceHeight,SpaceWidth,SpaceHeight);
KeysPoint.X += SpaceWidth*2;
}
//画Bar上的数值,不和上边同时进行操作是因为Bar柱有可能覆盖了数值的显示,所以要分开
for(int i=0;i < Values.Length;i++)
{
SpaceHeight = (Height-100)*(Values[i]/MaxValues(Values));
KeysTextPoint.Y = (int)(KeysPoint.Y - SpaceHeight - 20);
objGraphics.DrawString(Values[i].ToString(),new Font("宋体",10),new SolidBrush(TextColor),KeysTextPoint);
KeysTextPoint.X += SpaceWidth*2;
}
}
private void DrawContent(ref Graphics objGraphics)
{
Point KeysPoint = new Point(20,Height - 20);
Point KeysTextPoint = new Point(20,Height - 20);
int SpaceWidth = (Width-120)/(Values.Length*2);
float SpaceHeight;
//画Bar
for(int i=0;i < Values.Length;i++)
{
SpaceHeight = (Height-100)*(Values[i]/MaxValues(Values));
objGraphics.DrawRectangle(new Pen(BorderColor,1),KeysPoint.X,KeysPoint.Y - SpaceHeight,SpaceWidth+1,SpaceHeight+1);
objGraphics.FillRectangle(new SolidBrush(GetColor(i)),KeysPoint.X,KeysPoint.Y - SpaceHeight,SpaceWidth,SpaceHeight);
KeysPoint.X += SpaceWidth*2;
}
//画Bar上的数值,不和上边同时进行操作是因为Bar柱有可能覆盖了数值的显示,所以要分开
for(int i=0;i < Values.Length;i++)
{
SpaceHeight = (Height-100)*(Values[i]/MaxValues(Values));
KeysTextPoint.Y = (int)(KeysPoint.Y - SpaceHeight - 20);
objGraphics.DrawString(Values[i].ToString(),new Font("宋体",10),new SolidBrush(TextColor),KeysTextPoint);
KeysTextPoint.X += SpaceWidth*2;
}
}
至此,Bar图绘制算是完成了,看看效果(经过缩放):
由于右边部分和标题没有进行缩放,所以图片小于300X300的时候会有部分重叠,呵呵,解决这个问题也不难,继续将它们也按图片比例缩放就OK了,呵呵
有批评或建议请留言或Email我:kenblove@gmail.com
点击下载源代码例子:bar.rar