Asp.net实例:C#代码绘制折线图

1.思路分析:

1.首先肯定是读取数据库,将数据表中的这三列数据查出来并放进三个数组中;

2.新建一个Bitmap,所有要画的图形用Graphics来实现;

3.依据屏幕坐标,先画出X轴和Y轴,再标上刻度;

4.以X轴和Y轴为基础,算出每个数据在屏幕上的相对坐标,并画成折线;

5.在数据点上画点,并标出数据值;

6.修饰图形,并标注文字等信息,结束。

2.数据的获取

1.从数据库中获取数据
建立数据库连接并查询,可以专门新建一个C#类来提高代码复用率,也可以只写一个函数。下面的代码是原作者写的一个C#类SQL_Connection,放在App_Code文件夹下,专门用来执行数据库操作(我直接新建了一个数据库helper类,前面的文章里已经有了)代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;

///
///公用的连接数据库的类
///
public class SQL_Connection
{
private string sql = null;

public SQL_Connection(string sql)
{
this.sql = sql;
}
public DataSet query()
{
string ConStr = "Data Source=……;Initial Catalog=……;Persist SecurityInfo=True;UserID=……;Password=……";
SqlConnection conn = new SqlConnection(ConStr);
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = this.sql;
cmd.CommandTimeout = 10000;
conn.Open();
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
adapter.Fill(ds);
conn.Close();
return ds;
}
}

2.在后台的CS文件中执行数据库查询,并将结果放在数组中,具体代码如下:

//查询数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
string sql = "select * from manqi_cx where manqpfl <>0 and manqpfl1<>0 and manqpfl2<>0 and bmid=2";
SQL_Connection sqlCon = new SQL_Connection(sql);
DataSet ds = sqlCon.query();

//将结果放进数组中
double[] manqpfl = new double[TotalMonths];
double[] manqpfl1 = new double[TotalMonths];
double[] manqpfl2 = new double[TotalMonths];
for (int i = 0; i
{
manqpfl[i] = Convert.ToDouble(ds.Tables[0].Rows[i]["manqpfl"]);
manqpfl1[i] = Convert.ToDouble(ds.Tables[0].Rows[i]["manqpfl1"]);
manqpfl2[i] = Convert.ToDouble(ds.Tables[0].Rows[i]["manqpfl2"]);
}

3.具体实现

1.新建Bitmap,并用Graphics来画图和标注文字,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
Bitmap image = new Bitmap(width, height);
Graphics graphics = Graphics.FromImage(image);
try
{
graphics.Clear(Color.White);
Font font = new Font("Arial", 9, FontStyle.Regular);//坐标刻度所使用的字体
Font font1 = new Font("宋体", 15, FontStyle.Regular);//图片标题所使用的字体
Font font2 = new Font("宋体", 10, FontStyle.Regular);//注释信息所使用的字体
LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Gray, Color.Gray, 1.2f, true);//绘制网格线的LinearGradientBrush
LinearGradientBrush brush2 = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Red, Color.Red, 1.2f, true);//注释信息的LinearGradientBrush
LinearGradientBrush brush3 = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Green, Color.Green, 1.2f, true);//注释信息的LinearGradientBrush
LinearGradientBrush brush4 = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Brown, Color.Brown, 1.2f, true);//注释信息的LinearGradientBrush

graphics.FillRectangle(Brushes.White, 0, 0, width, height);
Brush brush1 = new SolidBrush(Color.Black);
if (manqpfl.Length > 0 & manqpfl1.Length > 0 & manqpfl2.Length > 0)
{
graphics.DrawString(" 从" + MinYear.ToString() + "年"+MinMonth.ToString()+"月到" + MaxYear.ToString() + "年"+MaxMonth.ToString()+"月的满期数据折线图", font1, brush1, new PointF(width / 2 - 200, 30));//标注图片标题
graphics.DrawString("商业险为红色折线", font2, brush2, new PointF(width / 2 + 200, 500));//标注注释信息
graphics.DrawString("交强险为绿色折线", font2, brush3, new PointF(width / 2 + 200, 530));//标注注释信息
graphics.DrawString("车 险为棕色折线", font2, brush4, new PointF(width / 2 + 200, 560));//标注注释信息
}
//画图片的边框线
graphics.DrawRectangle(new Pen(Color.Black), 0, 0, image.Width - 1, image.Height - 1);

//绘制Y轴
int x = 60;
Pen mypen1 = new Pen(Color.Black, 2);
graphics.DrawLine(mypen1, x, 120, x, 458);
//绘制网格纵线
Pen mypen = new Pen(brush, 1);
for (int i = 0; i < TotalMonths; i++)
{
graphics.DrawLine(mypen, x, 120, x, 458);
x = x + 60; //Y轴上每60像素为一个单位刻度
}
//绘制网格横线
int y = 158;
for (int i = 0; i < 5; i++)
{
graphics.DrawLine(mypen, 60, y, width-15, y);
y = y + 60; //X轴上每60像素为一个单位刻度
}
//绘制X轴
graphics.DrawLine(mypen1, 60, y, width-15, y);

//标注x轴文字
x = 35;
for (int i = 0; i < TotalMonths; i++)
{
string month= ds.Tables[0].Rows[i]["yy"].ToString() + "." + ds.Tables[0].Rows[i]["mm"].ToString();
graphics.DrawString(month.ToString(), font, Brushes.Red, x, 460); //设置文字内容及输出位置
x = x + 60; //X轴上每60像素为一个单位刻度
}
//y轴文字
String[] m = { " 90", " 80", " 70", " 60", " 50" ," 40"};
y = 150;
for (int i = 0; i < 6; i++)
{
graphics.DrawString(m[i].ToString(), font, Brushes.Red, 25, y); //设置文字内容及输出位置
y = y + 60; //Y轴上每60像素为一个单位刻度
}

int[] Count = new int[TotalMonths];
int[] Count1 = new int[TotalMonths];
int[] Count2 = new int[TotalMonths];
for (int j = 0; j < TotalMonths; j++)
{
Count[j] = Convert.ToInt32(manqpfl[j] * 360 / 60);//求数据点对坐标轴的相对位移
Count1[j] = Convert.ToInt32(manqpfl1[j] * 360 / 60);
Count2[j] = Convert.ToInt32(manqpfl2[j] * 360 / 60);
}

Point[] myPoint = caculatePoints(Count, TotalMonths);//求出数据点在屏幕上的绝对位置
Point[] myPoint1 = caculatePoints(Count1, TotalMonths);
Point[] myPoint2 = caculatePoints(Count2, TotalMonths);

Pen mypen2 = new Pen(Color.Red, 2);//manqpfl折线为红色
Pen mypen3 = new Pen(Color.Green, 2);//manqpfl1折线为绿色
Pen mypen4 = new Pen(Color.Brown, 2);//manqpfl2折线为棕色

graphics.DrawLines(mypen2, myPoint); //绘制manqpfl折线
graphics.DrawLines(mypen3, myPoint1); //绘制manqpfl1折线
graphics.DrawLines(mypen4, myPoint2); //绘制manqpfl2折线

//标注数据点的值
for (int i = 0; i < TotalMonths;i++ )
{
graphics.DrawString(manqpfl[i].ToString(), font, Brushes.Blue, myPoint[i].X-8, myPoint[i].Y-15);
graphics.DrawString(manqpfl1[i].ToString(), font, Brushes.Blue, myPoint1[i].X-8, myPoint1[i].Y-15);
graphics.DrawString(manqpfl2[i].ToString(), font, Brushes.Blue, myPoint2[i].X-8, myPoint2[i].Y-15);
}

//输出Bitmap
System.IO.MemoryStream MStream = new System.IO.MemoryStream();
image.Save(MStream, System.Drawing.Imaging.ImageFormat.Gif);
Response.ClearContent();
Response.ContentType = "image/Gif";
Response.BinaryWrite(MStream.ToArray());
//this.mess.InnerHtml = MStream.ToArray().ToString();
}
finally
{
graphics.Dispose();
image.Dispose();
}

//计算折线中点的坐标
protected Point[] caculatePoints(int[] Count,int TotalNumber)
{
Point[] myPoint = new Point[TotalNumber];
for (int i = 0; i < TotalNumber; i++)
{
myPoint[i].X = 60 + i * 60; myPoint[i].Y = 700 - Count[i];
}
return myPoint;
}

举例说明:

新建一个网页为Default3.aspx;

然后直接在Default3.aspx.cs后台页面中写代码,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;

public partial class Default3 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

//初始化数据

double[] manqpfl0 ={ 2009.1, 2009.2, 2009.3, 2009.4, 2009.5, 2009.6, 2009.7, 2009.8, 2009.9, 2009.10, 2009.11, 2009.12, 2010.1, 2010.2, 2010.3 };
double[] manqpfl = { 84, 85, 86, 84, 85, 84, 86, 87, 85, 84, 88, 87, 84, 85, 87 };
double[] manqpfl1 = { 72, 71, 71, 72, 71, 72, 71, 72, 71, 72, 71, 72, 71, 72, 717 };
double[] manqpfl2 = { 60, 61, 60, 61, 60, 61, 60, 61, 60, 61, 60, 61, 60, 61, 62 };
int TotalMonths = 14;


Bitmap image = new Bitmap(1000, 1000);
Graphics graphics = Graphics.FromImage(image);
try
{
graphics.Clear(Color.White);
Font font = new Font("Arial", 9, FontStyle.Regular);//坐标刻度所使用的字体
Font font1 = new Font("宋体", 15, FontStyle.Regular);//图片标题所使用的字体
Font font2 = new Font("宋体", 10, FontStyle.Regular);//注释信息所使用的字体
LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Gray, Color.Gray, 1.2f, true);//绘制网格线的LinearGradientBrush
LinearGradientBrush brush2 = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Red, Color.Red, 1.2f, true);//注释信息的LinearGradientBrush
LinearGradientBrush brush3 = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Green, Color.Green, 1.2f, true);//注释信息的LinearGradientBrush
LinearGradientBrush brush4 = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Brown, Color.Brown, 1.2f, true);//注释信息的LinearGradientBrush

graphics.FillRectangle(Brushes.White, 0, 0, 1000, 1000);
Brush brush1 = new SolidBrush(Color.Black);

//判断是否有数据
if (manqpfl.Length > 0 & manqpfl1.Length > 0 & manqpfl2.Length > 0)
{
graphics.DrawString(" 从2009年1月到2010年3月的满期数据折线图", font1, brush1, new PointF(1000 / 2 - 200, 30));//标注图片标题
graphics.DrawString("商业险为红色折线", font2, brush2, new PointF(1000 / 2 + 200, 500));//标注注释信息
graphics.DrawString("交强险为绿色折线", font2, brush3, new PointF(1000 / 2 + 200, 530));//标注注释信息
graphics.DrawString("车 险为棕色折线", font2, brush4, new PointF(1000 / 2 + 200, 560));//标注注释信息
}
//画图片的边框线
graphics.DrawRectangle(new Pen(Color.Black), 0, 0, image.Width - 1, image.Height - 1);

//绘制Y轴
int x = 60;
Pen mypen1 = new Pen(Color.Black, 2);
graphics.DrawLine(mypen1, x, 120, x, 458);
//绘制网格纵线
Pen mypen = new Pen(brush, 1);
for (int i = 0; i < TotalMonths; i++)
{
graphics.DrawLine(mypen, x, 120, x, 458);
x = x + 60; //Y轴上每60像素为一个单位刻度
}
//绘制网格横线
int y = 158;
for (int i = 0; i < 5; i++)
{
graphics.DrawLine(mypen, 60, y, 1000 - 15, y);
y = y + 60; //X轴上每60像素为一个单位刻度
}
//绘制X轴
graphics.DrawLine(mypen1, 60, y, 1000 - 15, y);

//标注x轴文字
x = 35;
for (int i = 0; i < TotalMonths; i++)
{
string month = manqpfl0[i].ToString(); //直接显示年月
graphics.DrawString(month.ToString(), font, Brushes.Red, x, 460); //设置文字内容及输出位置
x = x + 60; //X轴上每60像素为一个单位刻度
}
//y轴文字
String[] m = { " 90", " 80", " 70", " 60", " 50", " 40" };
y = 150;
for (int i = 0; i < 6; i++)
{
graphics.DrawString(m[i].ToString(), font, Brushes.Red, 25, y); //设置文字内容及输出位置
y = y + 60; //Y轴上每60像素为一个单位刻度
}

int[] Count = new int[TotalMonths];
int[] Count1 = new int[TotalMonths];
int[] Count2 = new int[TotalMonths];
for (int j = 0; j < TotalMonths; j++)
{
Count[j] = Convert.ToInt32(manqpfl[j] * 360 / 60);//求数据点对坐标轴的相对位移
Count1[j] = Convert.ToInt32(manqpfl1[j] * 360 / 60);
Count2[j] = Convert.ToInt32(manqpfl2[j] * 360 / 60);
}

Point[] myPoint = caculatePoints(Count, TotalMonths);//求出数据点在屏幕上的绝对位置
Point[] myPoint1 = caculatePoints(Count1, TotalMonths);
Point[] myPoint2 = caculatePoints(Count2, TotalMonths);

Pen mypen2 = new Pen(Color.Red, 2);//manqpfl折线为红色
Pen mypen3 = new Pen(Color.Green, 2);//manqpfl1折线为绿色
Pen mypen4 = new Pen(Color.Brown, 2);//manqpfl2折线为棕色

graphics.DrawLines(mypen2, myPoint); //绘制manqpfl折线
graphics.DrawLines(mypen3, myPoint1); //绘制manqpfl1折线
graphics.DrawLines(mypen4, myPoint2); //绘制manqpfl2折线

//标注数据点的值
for (int i = 0; i < TotalMonths; i++)
{
graphics.DrawString(manqpfl[i].ToString(), font, Brushes.Blue, myPoint[i].X - 8, myPoint[i].Y-15);
graphics.DrawString(manqpfl1[i].ToString(), font, Brushes.Blue, myPoint1[i].X - 8, myPoint1[i].Y - 15);
graphics.DrawString(manqpfl2[i].ToString(), font, Brushes.Blue, myPoint2[i].X - 8, myPoint2[i].Y - 15);
}

//输出Bitmap
System.IO.MemoryStream MStream = new System.IO.MemoryStream();
image.Save(MStream, System.Drawing.Imaging.ImageFormat.Gif);
Response.ClearContent();
Response.ContentType = "image/Gif";
Response.BinaryWrite(MStream.ToArray());

}
finally
{
graphics.Dispose();
image.Dispose();
}
}



//计算折线中点的坐标
protected Point[] caculatePoints(int[] Count,int TotalNumber)
{
Point[] myPoint = new Point[TotalNumber];
for (int i = 0; i < TotalNumber; i++)
{
myPoint[i].X = 60 + i * 60; myPoint[i].Y = 700 - Count[i];
}
return myPoint;
}
}

这样就可以完成折线图的绘制了!