先上效果圖:
餅圖:

條形圖:


通過在網上找資料,自己稍微整理下,注釋配代碼如下:
1、畫餅圖的全部代碼
/// <summary>
/// 根據四率 得到扇形圖
/// </summary>
/// <param name="width"></param>
/// <param name="heigh"></param>
/// <param name="r">餅圖半徑</param>
/// <param name="familyName"></param>
/// <param name="data"></param>
/// <returns></returns>
public Bitmap GetBitmap(int width, int heigh, int r,string familyName, Dictionary<string, double> data)
{
Bitmap bitmap = new Bitmap(width, heigh);
Graphics graphics = Graphics.FromImage(bitmap);
//用白色填充整個圖片,因為默認是黑色
graphics.Clear(Color.White);
//抗鋸齒
graphics.SmoothingMode = SmoothingMode.HighQuality;
//高質量的文字
graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
//像素均偏移0.5個單位,以消除鋸齒
graphics.PixelOffsetMode = PixelOffsetMode.Half;
//第一個色塊的原點位置
PointF basePoint = new PointF(10, 20);
//色塊的大小
SizeF theSize = new SizeF(45, 16);
//第一個色塊的說明文字的位置
PointF textPoint = new PointF(basePoint.X + 50, basePoint.Y);
foreach (var item in data)
{
RectangleF baseRectangle = new RectangleF(basePoint, theSize);
//畫代表色塊
graphics.FillRectangle(new SolidBrush(getColor(item.Key.ToString())), baseRectangle);
graphics.DrawString(item.Key.ToString(), new Font(familyName, 11), Brushes.Black, textPoint);
basePoint.Y += 30;
textPoint.Y += 30;
}
//扇形區所在邊框的原點位置
Point circlePoint = new Point(Convert.ToInt32( textPoint.X+90),35);
//總比 初始值
float totalRate = 0;
//起始角度 Y周正方向
float startAngle = 30;
//當前比 初始值
float currentRate = 0;
//圓所在邊框的大小
Size cicleSize=new Size(r*2,r*2);
//圓所在邊框的位置
Rectangle circleRectangle=new Rectangle(circlePoint,cicleSize);
foreach (var item in data) totalRate += float.Parse(item.Value.ToString());
foreach (var item in data)
{
currentRate = float.Parse(item.Value.ToString()) / totalRate * 360;
graphics.DrawPie(Pens.White, circleRectangle, startAngle, currentRate);
graphics.FillPie(new SolidBrush(getColor(item.Key.ToString())), circleRectangle, startAngle, currentRate);
//至此 扇形圖已經畫完,下面是在扇形圖上寫上說明文字
//當前圓的圓心 相對圖片邊框原點的坐標
PointF cPoint = new PointF(circlePoint.X+r, circlePoint.Y+r);
//當前圓弧上的點
//cos(弧度)=X軸坐標/r
//弧度=角度*π/180
double relativeCurrentX = r * Math.Cos((360 - startAngle - currentRate / 2) * Math.PI / 180);
double relativecurrentY = r * Math.Sin((360 - startAngle - currentRate / 2) * Math.PI / 180);
double currentX = relativeCurrentX+cPoint.X;
double currentY = cPoint.Y - relativecurrentY;
//內圓上弧上的 浮點型坐標
PointF currentPoint=new PointF(float.Parse(currentX.ToString()),float.Parse(currentY.ToString()));
//外圓弧上的點
double largerR = r + 25;
double relativeLargerX = largerR * Math.Cos((360 - startAngle - currentRate / 2) * Math.PI / 180);
double relativeLargerY = largerR * Math.Sin((360 - startAngle - currentRate / 2) * Math.PI / 180);
double largerX = relativeLargerX + cPoint.X;
double largerY = cPoint.Y - relativeLargerY;
//外圓上弧上的 浮點型坐標
PointF largerPoint=new PointF(float.Parse(largerX.ToString()),float.Parse(largerY.ToString()));
//將兩個點連起來
//graphics.DrawLine(Pens.Black, currentPoint, largerPoint);
//外圓上 說明文字的位置
PointF circleTextPoint = new PointF(float.Parse( largerX.ToString()),float.Parse( largerY.ToString()));
//在外圓上的點的附近合適的位置 寫上說明
if (largerX >= 0 && largerY >= 0)//第1象限 實際第二象限
{
//circleTextPoint.Y -= 15;
circleTextPoint.X -= 35;
}
if (largerX <= 0 && largerY >= 0)//第2象限 實際第三象限
{
//circleTextPoint.Y -= 15;
//circleTextPoint.X -= 65;
}
if (largerX <= 0 && largerY <= 0)//第3象限 實際第四象限
{
//circleTextPoint.X -= 45;
circleTextPoint.Y += 30;
}
if (largerX >= 0 && largerY <= 0)//第4象限 實際第一象限
{
circleTextPoint.X -= 15;
//circleTextPoint.Y += 5;
}
//象限差異解釋:在數學中 二維坐標軸中 右上方 全為正,在計算機處理圖像時,右下方全為正。相當於順時針移了一個象限序號
graphics.DrawString(item.Key.ToString() + " " + (currentRate/360).ToString("p2"), new Font(familyName, 11), Brushes.Black, circleTextPoint);
startAngle += currentRate;
}
return bitmap;
}
2、獲得配色的代碼:
Color getColor(string scoreLevel) {
Color c=Color.White;
if (scoreLevel.Contains("優秀"))
c = Color.FromArgb(57,134,155);
if (scoreLevel.Contains("良好"))
c = Color.FromArgb(70,161,185);
if (scoreLevel.Contains("一般"))
c = Color.FromArgb(124,187,207);
if (scoreLevel.Contains("不及格"))
c = Color.FromArgb(181,212,224);
return c;
}
3、畫條形圖的代碼
/// <summary>
/// 獲得柱狀圖
/// </summary>
/// <param name="width"></param>
/// <param name="heigh"></param>
/// <param name="familyName"></param>
/// <param name="data"></param>
/// <param name="PaperScore"></param>
/// <returns></returns>
public Bitmap GetBargraph(int width, int heigh, string familyName, Dictionary<string, double> data, int PaperScore)
{ if (data != null)
{
Bitmap bitmap = new Bitmap(width, heigh);
Graphics graphics = Graphics.FromImage(bitmap);
//用白色填充整個圖片,因為默認是黑色
graphics.Clear(Color.White);
//抗鋸齒
graphics.SmoothingMode = SmoothingMode.HighQuality;
//高質量的文字
graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
//像素均偏移0.5個單位,以消除鋸齒
graphics.PixelOffsetMode = PixelOffsetMode.Half;
double maxCount = 0;
//以最多人數為基准
foreach (var item in data) if (Convert.ToDouble(item.Value.ToString()) > maxCount)
maxCount = Convert.ToDouble(item.Value.ToString());
//在距離底部25像素的地方 畫上分數線 並標上四個分數
//該分數線的寬度是圖片寬度的85%
//分數線原點位置
PointF scoreLineStartPoint = new PointF(width * 0.15f / 2f, heigh - 25f);
//分數線終點位置
PointF scoreLineEndPoint = new PointF(scoreLineStartPoint.X + width * 0.85f, scoreLineStartPoint.Y);
graphics.DrawLine(Pens.Black, scoreLineStartPoint, scoreLineEndPoint);
//定義:最多人數的那項占圖片高度的85%
//每項*高度的85%/maxCount=該項的高度
float currentX = width * 0.85f * (1f / 9)//直線上的1/9處為起點
+ width * 0.15f / 2// 圖片的兩邊 空 15% ,每邊空15%的一半 ;
float perWidth = width * 0.85f * (1f / 9);
foreach (var item in data)
{
//當前等級的原點描述:Height-25-(人數*0.9/maxcount)
float currentHeight = (float)item.Value * 0.85f * heigh / (float)maxCount;
//顏色 全部用淡藍色
graphics.FillRectangle(new SolidBrush(Color.FromArgb(70, 161, 187)), currentX, heigh - 25 - currentHeight - 1, perWidth, currentHeight);
//畫當前區間的左邊的線
graphics.DrawLine(Pens.Black, currentX, scoreLineStartPoint.Y, currentX, scoreLineStartPoint.Y + 3);
//在上面5像素處寫上人數
graphics.DrawString(item.Value.ToString() + "(人)", new Font(familyName, 11), Brushes.Black, currentX - 4, heigh - 25 - currentHeight - 1 - 18);
graphics.DrawString(item.Key.ToString(), new Font(familyName, 11), Brushes.Black, currentX, scoreLineStartPoint.Y + 3);
currentX += perWidth;//向右移一個柱形寬度單位
//畫當前區間的右邊的線
graphics.DrawLine(Pens.Black, currentX, scoreLineStartPoint.Y, currentX, scoreLineStartPoint.Y + 3);
currentX += perWidth;//向右移一個柱形寬度單位 }
graphics.DrawString("(等級)", new Font(familyName, 11), Brushes.Black, currentX - perWidth + 3f, scoreLineStartPoint.Y + 3);
return bitmap; } else return null; }
4、調用柱狀圖的一般處理程序(餅圖類似)
string datas = context.Request.QueryString["data"];
ScoreStatistics s = new ScoreStatistics();
data = s.TransferToObject<Dictionary<string, double>>(datas);
MemoryStream mem = new MemoryStream();
Bitmap chart = scoreStaticsBLL.GetBargraph(450, 280, "宋體", data, 120);
chart.Save(mem, ImageFormat.Jpeg);
context.Response.ContentType = "image/jpeg";
context.Response.BinaryWrite(mem.ToArray());
調用圖片的頁面代碼就是一個 圖片控件,src的地址為上面的一般處理程序的相對網站地址
