图形库






4.84/5 (41投票s)
本文介绍了使用 C# 构建一个简单的图形库。




引言
.NET Framework 中的图形是一个强大的功能,可以适用于广泛的用途。 在这里,我开发了一个类来演示使用图形创建如下所示的图表:
- 条形图
- 饼图
- 折线图
Using the Code
附加的项目包含一个名为DrawGraph.cs的文件,它是一个用于生成图表的通用库。 此库中的方法生成诸如单维度条形图、3D 条形图、单维度饼图、3D 饼图和折线图之类的图表。 所有图表都以位图格式生成。 下面的代码演示了如何在 Windows 应用程序中使用此库。
// Values used to create graph
string [] keyValue=new string[ui_lbx_DataKey.Items.Count];
float[] values = new float[ui_lbx_DataKey.Items.Count];
for (int i = 0; i < ui_lbx_DataKey.Items.Count; i++)
{
keyValue[i] = ui_lbx_DataKey.Items[i].ToString();
values[i] = float.Parse(ui_lbx_DataValue.Items[i].ToString());
}
//Include namespace System.Anoop.Graph and initiaze the
//bargraph object with values,label on x & y axis, font format and alpha
DrawGraph bargraph = new DrawGraph(keyValue, values,
ui_txt_xlabel.Text, ui_txt_ylabel.Text,
"Courier", 255);
//Generating graph and assigning it to respective picture box
p1.Image = bargraph.DrawBarGraph();
p2.Image = bargraph.Draw3dBarGraph();
p3.Image = bargraph.DrawPieGraph();
p4.Image = bargraph.Draw3DPieGraph();
//Generating Line graph
DrawGraph bargraph1 = new DrawGraph(keyValue, values,
ui_txt_xlabel.Text, ui_txt_ylabel.Text,
"Courier", 255);
p5.Image = bargraph1.DrawLineGraph();
下面的代码演示了如何在 ASP.NET 应用程序中使用此库。
DrawGraph bargraph = new DrawGraph(keyValue, values,
"Financial Year","Profit", "Courier", 255);
//Generating graph and assigning it to respective imagebox
System.Drawing.Bitmap b = new System.Drawing.Bitmap(400, 400);
b = bargraph.DrawLineGraph();
b.Save(Server.MapPath("Graph")+"\\LineGraph.bmp");
Image1.ImageUrl =".\\Graph\\LineGraph.bmp";
System.Drawing.Bitmap b1 = new System.Drawing.Bitmap(400, 400);
b1 = bargraph.DrawPieGraph();
b1.Save(Server.MapPath("Graph") + "\\PieGraph.bmp");
Image2.ImageUrl = ".\\Graph\\PieGraph.bmp";
System.Drawing.Bitmap b2 = new System.Drawing.Bitmap(400, 400);
b2 = bargraph.Draw3DPieGraph();
b2.Save(Server.MapPath("Graph") + "\\3DPieGraph.bmp");
Image3.ImageUrl = ".\\Graph\\3DPieGraph.bmp";
System.Drawing.Bitmap b3 = new System.Drawing.Bitmap(400, 400);
b3 = bargraph.Draw3dBarGraph();
b3.Save(Server.MapPath("Graph") + "\\3dBarGraph.bmp");
Image4.ImageUrl = ".\\Graph\\3dBarGraph.bmp";
代码
在类的开始处有一些导入。 这些导入是为了处理图像文件而包含的。
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Drawing;
现在是全局变量。
string[] valueLabels; float[] values;
string xLabel;
//Label displayed on x axis
string yLabel;
//Label displayed on y axis
string fontFormat;
//format for labels
int alpha;
//alpha for graph
List <color> colorList;
//Dark colors only
这些全局变量正在使用构造函数进行初始化。
public DrawGraph(string[] valueLabels,float[] values,string xLabel,string
yLabel,string fontFormat,int alpha)
{
this.valueLabels = valueLabels;
this.values = values;
this.xLabel = xLabel;
this.yLabel = yLabel;
this.alpha = alpha;
this.fontFormat=fontFormat;
InitColorList();
}
这里InitColorList()
是一个用深色初始化colorList
的方法。
//Initiatialize color list with dark color's
private void InitColorList()
{
colorList = new List();
foreach (string colorName in Enum.GetNames(typeof(System.Drawing.KnownColor)))
{
//Check if color is dark
if (colorName.StartsWith("D") == true)
{
colorList.Add(System.Drawing.Color.FromName(colorName));
}
}
}
//Embed axis for bar graphs
在这个类中,我们还有一些私有方法,如EmbedAxis()
,EmbedXPanel()
和EmbedXLinePanel()
。 这些用于创建轴,创建 x 轴值与颜色的映射,并分别创建 x 轴值与线条颜色的映射。
Bitmap EmbedAxis(Bitmap graph,bool showAxis)
{
Bitmap backgroundCanvas = new Bitmap(400, 300);
Bitmap yLabelImage = new Bitmap(15,200);
Graphics graphicsBackImage = Graphics.FromImage(backgroundCanvas);
Graphics objGraphic2 = Graphics.FromImage(graph);
Graphics objGraphicY = Graphics.FromImage(yLabelImage);
Pen blackPen = new Pen(Color.Black, 2);
//Paint the graph canvas white SolidBrush
whiteBrush = new SolidBrush(Color.White);
graphicsBackImage.FillRectangle(whiteBrush,0, 0, 400, 300);
if (showAxis == true)
{
//draw lable for y axis
StringFormat sf = new StringFormat(StringFormatFlags.DirectionVertical);
Font f = new Font(fontFormat,8);
SizeF sizef = objGraphicY.MeasureString("<- " + yLabel, f, Int32.MaxValue,sf);
RectangleF rf = new RectangleF(0, 0, sizef.Width, sizef.Height);
objGraphicY.DrawRectangle(Pens.Transparent,rf.Left, rf.Top, rf.Width, rf.Height);
objGraphicY.DrawString((yLabel.Length>0?"<-":"") + yLabel,
f, Brushes.Black, rf, sf);
graphicsBackImage.DrawString(xLabel +(xLabel.Length>0?" ->":""),
f, Brushes.Black, 30, 235);
graphicsBackImage.DrawLine(blackPen,new Point(0, 230), new Point(230, 230));
graphicsBackImage.DrawLine(blackPen, new Point(20, 20), new Point(20, 250));
}
graphicsBackImage.DrawImage(graph, 25, 25);
if (showAxis == true)
{
graphicsBackImage.DrawImage(yLabelImage, 0, 90);
}
return (backgroundCanvas);
}
//Embed x Panel
Bitmap EmbedXPanel(Bitmap graph)
{
Bitmap xPanel = new Bitmap(100, 200);
Graphics objGraphicPanel = Graphics.FromImage(xPanel);
Graphics graphicGraph = Graphics.FromImage(graph);
for (int i = 0, x = 10; i <values.Length; i++)
{
//Draw the bar
SolidBrush brush = new SolidBrush(Color.FromArgb(alpha,colorList[i]));
objGraphicPanel.FillRectangle(brush, 10, 190 - x, 10, 10);
string drawString = valueLabels[i] + " = " + values[i].ToString();
Font drawFont = new Font(fontFormat, 8);
SolidBrush drawBrush = new SolidBrush(Color.Black);
objGraphicPanel.DrawString(drawString,drawFont, drawBrush, 20, 190 - x);
//x axis spacing by 20
x += 20;
}
graphicGraph.DrawImage(xPanel,300, 25); return (graph);
}
//Embed x Panel[Line graph style]
Bitmap EmbedXLinePanel(Bitmap graph)
{
Bitmap xPanel = new Bitmap(100, 200);
Graphics objGraphicPanel = Graphics.FromImage(xPanel);
Graphics graphicGraph = Graphics.FromImage(graph);
for (int i = 1, x = 10; i < values.Length; i++)
{
//Draw the bar
SolidBrush brush = new SolidBrush(Color.FromArgb(alpha,colorList[i]));
Pen colorPen = new Pen(brush,2);
objGraphicPanel.DrawLine(colorPen,10, 190 - x, 20, 190 - x);
string drawString = valueLabels[i - 1].ToString() + " - " + valueLabels[i].ToString();
Font drawFont = new Font(fontFormat, 8);
SolidBrush drawBrush = new SolidBrush(Color.Black);
objGraphicPanel.DrawString(drawString, drawFont, drawBrush, 20, 190 - x);
//x axis spacing by 20
x += 20;
}
graphicGraph.DrawImage(xPanel,300, 25);
return (graph);
}
让我们来看看创建条形图的方法。这里,该方法遵循一个简单的算法。
- 首先准备一个尺寸为 200 X 200 的白色画布。
- 计算最高值 [x 轴值]。
- 对于 x 轴上的每个值...
- 使用公式计算条形高度:条形高度=(x 值 / 最高值)* 190。
- 绘制条形。
- 使用
EmbedAxis()
绘制轴并将条形图放置在放大的画布上。 - 使用
EmbedXPanel()
将 x 值映射到颜色。
//Generate Bar graph
public Bitmap DrawBarGraph()
{
Bitmap objgraph = new Bitmap(200, 200);
// Canvas for graph
Graphics graphicGraph = Graphics.FromImage(objgraph);
//Paint the graph canvas white
SolidBrush whiteBrush = new SolidBrush(Color.White);
graphicGraph.FillRectangle(whiteBrush,0, 0, 200, 200);
float highestValue;
//Highest value in the values array
//Get the highest value
float[] tempValue = new float[values.Length];
for (int j = 0; j < values.Length; j++)
{
tempValue[j] = values[j]; } Array.Sort<float>(tempValue);
highestValue = tempValue[values.Length - 1];
//Generate bar for each value
for (int i = 0, x = 10; i < values.Length; i++)
{
float barHeight;
//hight of the bar
barHeight = (values[i] / highestValue) * 190;
//Draw the bar
SolidBrush brush = new SolidBrush(Color.FromArgb(alpha, colorList[i]));
graphicGraph.FillRectangle(brush,x, 194 - barHeight, 10, barHeight);
//x axis spacing by 20
x += 20;
}
//
Increase the size of the canvas and draw axis
objgraph = EmbedAxis(objgraph, true);
//Draw the key-value pair with repective color code
objgraph = EmbedXPanel(objgraph);
return (objgraph);
}
绘制 3D 条形图与上述条形图的代码类似,除了我们需要执行一些额外的任务,例如:
- 绘制阴影。
- 在图表的底部绘制一条白线以隐藏阴影。
public Bitmap Draw3dBarGraph()
{
Bitmap objgraph = new Bitmap(200, 200);
//Canvas for graph
Bitmap objXValuePanel = new Bitmap(100,200);
//Canvas to display x-axis values
Graphics graphicGraph = Graphics.FromImage(objgraph);
Graphics graphicXValuePanel = Graphics.FromImage(objXValuePanel);
//Paint the graph canvas white
SolidBrush whiteBrush = new SolidBrush(Color.White);
graphicGraph.FillRectangle(whiteBrush,0, 0, 200, 200);
float highestValue;
//Highest value in the values array
//Get the highest value
float[] tempValue = new float[values.Length];
for (int j = 0; j < values.Length; j++)
{
tempValue[j] = values[j];
}
Array.Sort<float>(tempValue);
highestValue = tempValue[values.Length - 1];
//Generate bar for each value
for (int i = 0, x = 10; i < values.Length; i++)
{
SolidBrush brush = new SolidBrush(Color.FromArgb(alpha,colorList[i]));
float barHeight;
//hight of the bar
barHeight = (values[i] / highestValue)* 190;
//Draw continuous shade for 3D effect
float shadex = x + 10; float shadey = 194 - ((int)barHeight) + 10;
for (int iLoop2 = 0; iLoop2 < 10; iLoop2++)
{
graphicGraph.FillRectangle(brush, shadex - iLoop2, shadey - iLoop2, 10, barHeight);
}
//Draw bar
graphicGraph.FillRectangle(new HatchBrush(HatchStyle.Percent50, brush.Color),
x, 194 - barHeight, 10, barHeight);
//Increment the x position
x += 20;
}
//Mask bottom with a white line
Pen whitePen = new Pen(Color.White, 10);
graphicGraph.DrawLine(whitePen,new Point(10, 200), new Point(230, 200));
//Increase the size of the canvas and draw axis
objgraph = EmbedAxis(objgraph, true);
//Draw the key-value pair with repective color code
objgraph = EmbedXPanel(objgraph);
return (objgraph);
}
要绘制饼图,请遵循以下算法:
- 首先准备一个尺寸为 200 X 200 的白色画布。
- 计算所有 x 值的总和 [x 轴值]。
- 将饼图的起始角度初始化为 0 度。
- 对于每个值...
- 使用公式计算
sweepAngle
:扫描角度 = (x 值 * 360) / 所有 x 值的总和。 - 绘制饼图。
- 用扫描角度增加起始角度。
- 使用公式计算
- 使用
EmbedAxis()
将饼图放置在放大的画布上,并将showAxis
标志设置为false
。 - 使用
EmbedXPanel()
将 x 值映射到颜色。
public Bitmap DrawPieGraph()
{
Bitmap objgraph = new Bitmap(200, 200);
Graphics graphicGraph = Graphics.FromImage(objgraph);
//Create location and size of ellipse.
int x = 0;
int y = 0;
int width = 200;
int height = 100;
//Create start and sweep
angles. float sweepAngle = 0;
float startAngle = 0;
float total = 0;
for (int i = 0; i < values.Length; i++)
{
total += values[i];
}
for (int i = 0; i < values.Length; i++)
{
SolidBrush objBrush = new SolidBrush(colorList[i]);
sweepAngle = (values[i] * 360) / total;
graphicGraph.SmoothingMode = SmoothingMode.AntiAlias;
graphicGraph.FillPie(objBrush, x, y, width, height, startAngle, sweepAngle);
startAngle += sweepAngle; }
//Increase the size of the canvas in which the graph resides
objgraph = EmbedAxis(objgraph, false);
//Draw the key-value pair with repective color code
objgraph = EmbedXPanel(objgraph); return (objgraph);
}
绘制 3D 饼图与绘制饼图类似,但需要添加一个额外的任务:绘制阴影。
Bitmap Draw3DPieGraph()
{
Bitmap objgraph = new Bitmap(200, 200);
Graphics graphicGraph = Graphics.FromImage(objgraph);
//Create location and size of ellipse.
int x =0;
int y = 0;
int width = 200;
int height = 100;
//Find the sum of all values float
total = 0; for (int i = 0; i < values.Length; i++)
{
total += values[i];
}
//When loop=0: Draw shadow
//loop=1: Draw graph
for (int loop = 0; loop < 2; loop++)
{
//Create start and sweep angles
float sweepAngle = 0;
float startAngle = 0;
//Draw pie for each value
for (int i = 0; i < values.Length; i++)
{
SolidBrush objBrush = new SolidBrush(colorList[i]);
sweepAngle = (values[i] * 360) / total;
graphicGraph.SmoothingMode = SmoothingMode.AntiAlias;
if (loop == 0)
{
for (int iLoop2 = 0; iLoop2 < 10; iLoop2++)
graphicGraph.FillPie(new HatchBrush(HatchStyle.Percent50,objBrush.Color),
x, y + iLoop2, width, height, startAngle, sweepAngle);
}
else
{
graphicGraph.FillPie(objBrush, x, y, width, height, startAngle, sweepAngle);
}
startAngle += sweepAngle;
}
}
//Increase the size of the canvas in which the graph resides
objgraph = EmbedAxis(objgraph, false);
//Draw the key-value pair with repective
color code objgraph = EmbedXPanel(objgraph);
return (objgraph);
}
要绘制折线图,我们使用与条形图相同的公式来计算高度。 一旦标记了点,只需使用不同颜色的线条连接它们即可。 必须使用 EmbedXLinePanel()
绘制 x-Panel。
//Generate Line graph
public Bitmap DrawLineGraph()
{
Bitmap objgraph = new Bitmap(200, 200);
//Canvas for graph
Graphics graphicGraph = Graphics.FromImage(objgraph);
//Paint the graph canvas white
SolidBrush whiteBrush = new SolidBrush(Color.White);
graphicGraph.FillRectangle(whiteBrush,0, 0, 200, 200);
int highestValue;
//Highest value in the values array
//Get the highest value
int[] tempValue = new int[values.Length];
for (int j = 0; j < values.Length;j++)
{
tempValue[j] = (int)values[j];
}
Array.Sort<int>(tempValue);
highestValue = tempValue[values.Length - 1];
int[,] points = new int[values.Length, 2];
//Generate bar for each value
for (int i = 0, x = 10; i < values.Length; i++)
{
decimal barHeight;
//height of the bar
barHeight = (decimal)(values[i] / highestValue * 190);
points[i, 0] = x; barHeight = 194 - barHeight;
points[i, 1] = (int)Decimal.Round(barHeight,0);
Font f = new Font(fontFormat, 8);
graphicGraph.FillEllipse(Brushes.Black, points[i,0]-2, points[i, 1]-2, 5, 5);
graphicGraph.DrawString(values[i].ToString(), f,
Brushes.Black,new Point(points[i, 0]-14, points[i, 1]-5));
x += 20;
}
for (int i = 1; i < values.Length; i++)
{
Point startPoint = new Point(points[i - 1, 0], points[i - 1, 1]);
Point endPoint = new Point(points[i, 0], points[i, 1]);
SolidBrush brush = new SolidBrush(colorList[i]); Pen colorPen = new Pen(brush, 2);
graphicGraph.DrawLine(colorPen, startPoint, endPoint);
}
objgraph = EmbedAxis(objgraph,true);
objgraph = EmbedXLinePanel(objgraph);
return (objgraph);
}
历史
- 2008 年 2 月 27 日 - 发布原始版本
- 2008 年 3 月 27 日 - 引入条形折线图