C#绘制成比例缩放的折线图
参照http://xxp5310776.blog.sohu.com/58914721.html
/// <summary>
/// 绘制双折线图
/// </summary>
/// <param name="bmap">空白位图</param>
/// <param name="iScaleX">X轴比例</param>
/// <param name="iScaleY">Y轴比例</param>
/// <param name="arrX">X轴数组</param>
/// <param name="arrY1">Y轴数组</param>
/// <param name="arrY2">Y轴数组</param>
/// <param name="strTitle">标题</param>
/// <param name="strXUnitName">X轴单位名称</param>
/// <param name="strYUnitName">Y周轴单位名称</param>
/// <param name="strY1Name">第1条折线图例名称</param>
/// <param name="strY2Name">第2条折线图例名称</param>
/// <param name="gph">返回绘制的折线图</param>
调用代码:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Drawing;
- using System.Drawing.Imaging;
- /// <summary>
- ///ClassDrawing 的摘要说明
- /// </summary>
- public class ClassDrawing
- {
- public ClassDrawing()
- {
- //
- //TODO: 在此处添加构造函数逻辑
- //
- }
- /// <summary>
- /// 绘制双折线图
- /// </summary>
- /// <param name="bmap">空白位图</param>
- /// <param name="iScaleX">X轴比例</param>
- /// <param name="iScaleY">Y轴比例</param>
- /// <param name="arrX">X轴数组</param>
- /// <param name="arrY1">Y轴数组</param>
- /// <param name="arrY2">Y轴数组</param>
- /// <param name="strTitle">标题</param>
- /// <param name="strXUnitName">X轴单位名称</param>
- /// <param name="strYUnitName">Y周轴单位名称</param>
- /// <param name="strY1Name">第1条折线图例名称</param>
- /// <param name="strY2Name">第2条折线图例名称</param>
- /// <param name="gph">返回绘制的折线图</param>
- public void drawLineGraphY2(ref Bitmap bmap, ref int iScaleX, ref int iScaleY, ref double[] arrX, ref double[] arrY1, ref double[] arrY2, ref string strTitle, ref string strXUnitName, ref string strYUnitName, ref string strY1Name, ref string strY2Name, out Graphics gph)
- {
- gph = Graphics.FromImage(bmap);
- gph.Clear(Color.White);
- if (arrX.Length != arrY1.Length)
- {
- return;
- }
- if (arrX.Length != arrY2.Length)
- {
- return;
- }
- double xMax = 0;
- double xUnit = 0;
- float[] arrXUnit = new float[arrX.Length];
- double yMax = 0;
- double yUnit = 0;
- float[] arrY1Unit = new float[arrY1.Length];
- float[] arrY2Unit = new float[arrY2.Length];
- // 按X从小到大进行排序
- for (int i = 0; i < arrX.Length; i++)
- {
- if (arrX[i] < 0)
- {
- return;
- }
- for (int j = i + 1; j < arrX.Length; j++)
- {
- if (arrX[i] > arrX[j])
- {
- double dTempX = arrX[i];
- double dTempY1 = arrY1[i];
- double dTempY2 = arrY2[i];
- arrX[i] = arrX[j];
- arrY1[i] = arrY1[j];
- arrY2[i] = arrY2[j];
- arrX[j] = dTempX;
- arrY1[j] = dTempY1;
- arrY2[j] = dTempY2;
- }
- }
- }
- // X轴数组的最大值
- xMax = arrX[arrX.Length - 1];
- if (xMax < 1)
- {
- for (int i = 0; i < 10; i++)
- {
- if ((xMax <= Math.Pow(10, -i)) && (xMax > Math.Pow(10, -(i + 1))))
- {
- if (xMax <= 5 * Math.Pow(10, -(i + 1)))
- {
- xMax = (5 * Math.Pow(10, -(i + 1)));
- }
- else
- {
- xMax = Math.Pow(10, -i);
- }
- break;
- }
- }
- }
- else
- {
- for (int i = 0; i < 10; i++)
- {
- if ((xMax > Math.Pow(10, i)) && (xMax <= Math.Pow(10, (i + 1))))
- {
- if (xMax <= 5 * Math.Pow(10, i))
- {
- xMax = (5 * Math.Pow(10, i));
- }
- else
- {
- xMax = Math.Pow(10, (i + 1));
- }
- break;
- }
- }
- }
- // X轴一个单位的大小
- xUnit = xMax / 10;
- for (int i = 0; i < arrX.Length; i++)
- {
- arrXUnit[i] = (float)(arrX[i] / xUnit);
- }
- // Y轴数组的最大值
- for (int i = 0; i < arrY1.Length; i++)
- {
- if (arrY1[i] < 0)
- {
- return;
- }
- if (yMax < arrY1[i])
- {
- yMax = arrY1[i];
- }
- }
- for (int i = 0; i < arrY2.Length; i++)
- {
- if (arrY2[i] < 0)
- {
- return;
- }
- if (yMax < arrY2[i])
- {
- yMax = arrY2[i];
- }
- }
- if (yMax < 1)
- {
- for (int i = 0; i < 10; i++)
- {
- if ((yMax <= Math.Pow(10, -i)) && (yMax > Math.Pow(10, -(i + 1))))
- {
- if (yMax <= 5 * Math.Pow(10, -(i + 1)))
- {
- yMax = (5 * Math.Pow(10, -(i + 1)));
- }
- else
- {
- yMax = Math.Pow(10, -i);
- }
- break;
- }
- }
- }
- else
- {
- for (int i = 0; i < 10; i++)
- {
- if ((yMax > Math.Pow(10, i)) && (yMax <= Math.Pow(10, (i + 1))))
- {
- if (yMax <= 5 * Math.Pow(10, i))
- {
- yMax = (5 * Math.Pow(10, i));
- }
- else
- {
- yMax = Math.Pow(10, (i + 1));
- }
- break;
- }
- }
- }
- // Y轴一个单位的大小
- yUnit = yMax / 10;
- for (int i = 0; i < arrX.Length; i++)
- {
- arrY1Unit[i] = (float)(arrY1[i] / yUnit);
- arrY2Unit[i] = (float)(arrY2[i] / yUnit);
- }
- PointF cpt = new PointF(iScaleX + 10, iScaleX + iScaleY * 13);//中心点
- PointF[] xpt = new PointF[3] { new PointF(iScaleX * 15 + 15, cpt.Y), new PointF(iScaleX * 15, cpt.Y - 8), new PointF(iScaleX * 15, cpt.Y + 8) };//x轴三角形
- PointF[] ypt = new PointF[3] { new PointF(cpt.X, cpt.X - 15), new PointF(cpt.X - 8, cpt.X), new PointF(cpt.X + 8, cpt.X) };//y轴三角形
- gph.DrawString(strTitle, new Font("宋体", 14), Brushes.Black, new PointF(cpt.X + iScaleX * 2, cpt.X));//图表标题
- // 第一条折线的图例
- gph.DrawLine(Pens.Red, iScaleX * 13, cpt.X + 5 + 10, iScaleX * 13 + 10, cpt.X + 5 + 10);
- gph.DrawString(strY1Name, new Font("宋体", 11), Brushes.Red, new PointF(iScaleX * 13 + 10, cpt.X + 10));//Y1
- // 第二条折线的图例
- gph.DrawLine(Pens.Blue, iScaleX * 13, cpt.X + 5 + 40, iScaleX * 13 + 10, cpt.X + 5 + 40);
- gph.DrawString(strY2Name, new Font("宋体", 11), Brushes.Blue, new PointF(iScaleX * 13 + 10, cpt.X + 40));//Y2
- //画x轴
- gph.DrawLine(Pens.Black, cpt.X, cpt.Y, iScaleX * 15, cpt.Y);
- gph.DrawPolygon(Pens.Black, xpt);
- gph.FillPolygon(new SolidBrush(Color.Black), xpt);
- gph.DrawString(strXUnitName, new Font("宋体", 12), Brushes.Black, new PointF(iScaleX * 15 + 10, cpt.Y + 10));
- //画y轴
- float fStartX = 0;
- if (iScaleX > 30)
- {
- fStartX = iScaleX - 30;
- }
- gph.DrawLine(Pens.Black, cpt.X, cpt.Y, cpt.X, cpt.X);
- gph.DrawPolygon(Pens.Black, ypt);
- gph.FillPolygon(new SolidBrush(Color.Black), ypt);
- gph.DrawString(strYUnitName, new Font("宋体", 12), Brushes.Black, new PointF(fStartX, 7));
- //画x轴项目
- for (int i = 1; i <= 12; i++)
- {
- gph.DrawString(Convert.ToString(i * xUnit), new Font("宋体", 11), Brushes.Black, new PointF(cpt.X + i * iScaleX - 5, cpt.Y + 10));
- gph.DrawLine(Pens.Black, cpt.X + i * iScaleX, cpt.Y, cpt.X + i * iScaleX, cpt.Y + 3);
- }
- //画y轴刻度
- for (int i = 1; i <= 10; i++)
- {
- gph.DrawString(Convert.ToString(i * yUnit), new Font("宋体", 11), Brushes.Black, new PointF(fStartX, cpt.Y - i * iScaleY - 6));
- gph.DrawLine(Pens.Black, cpt.X - 3, cpt.Y - i * iScaleY, cpt.X, cpt.Y - i * iScaleY);
- }
- for (int i = 1; i <= arrX.Length; i++)
- {
- /*
- * 第一条折线
- */
- //画点
- gph.DrawEllipse(Pens.Black, cpt.X + arrXUnit[i - 1] * iScaleX - 1.5f, cpt.Y - arrY1Unit[i - 1] * iScaleY - 1.5f, 3, 3);
- gph.FillEllipse(new SolidBrush(Color.Black), cpt.X + arrXUnit[i - 1] * iScaleX - 1.5f, cpt.Y - arrY1Unit[i - 1] * iScaleY - 1.5f, 3, 3);
- //画数值
- gph.DrawString(arrY1[i - 1].ToString(".00"), new Font("宋体", 11), Brushes.Red, new PointF(cpt.X + arrXUnit[i - 1] * iScaleX, cpt.Y - arrY1Unit[i - 1] * iScaleY));
- //画折线
- if (i > 1)
- {
- gph.DrawLine(Pens.Red, cpt.X + arrXUnit[i - 2] * iScaleX, cpt.Y - (float)arrY1Unit[i - 2] * iScaleY, cpt.X + arrXUnit[i - 1] * iScaleX, cpt.Y - arrY1Unit[i - 1] * iScaleY);
- }
- /*
- * 第二条折线
- */
- //画点
- gph.DrawEllipse(Pens.Black, cpt.X + arrXUnit[i - 1] * iScaleX - 1.5f, cpt.Y - arrY2Unit[i - 1] * iScaleY - 1.5f, 3, 3);
- gph.FillEllipse(new SolidBrush(Color.Black), cpt.X + arrXUnit[i - 1] * iScaleX - 1.5f, cpt.Y - arrY2Unit[i - 1] * iScaleY - 1.5f, 3, 3);
- //画数值
- gph.DrawString(arrY2[i - 1].ToString(".00"), new Font("宋体", 11), Brushes.Blue, new PointF(cpt.X + arrXUnit[i - 1] * iScaleX, cpt.Y - arrY2Unit[i - 1] * iScaleY));
- //画折线
- if (i > 1)
- {
- gph.DrawLine(Pens.Blue, cpt.X + arrXUnit[i - 2] * iScaleX, cpt.Y - (float)arrY2Unit[i - 2] * iScaleY, cpt.X + arrXUnit[i - 1] * iScaleX, cpt.Y - arrY2Unit[i - 1] * iScaleY);
- }
- }
- }
- }
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.Linq;
- using System.Web;
- using System.Web.UI;
- using System.Web.UI.WebControls;
- public partial class Default3 : System.Web.UI.Page
- {
- protected void Page_Load(object sender, EventArgs e)
- {
- /*
- * 画图初始化
- */
- int iScaleX = 20;
- int iScaleY = 20;
- // 空白位图
- Bitmap bmap = new System.Drawing.Bitmap(iScaleX * 16 + 100, iScaleY * 16 + 50);
- // X轴数组
- double[] arrX = new double[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
- // Y轴数组
- double[] arrY1 = new double[10] { 20.5f, 60, 10.8f, 15.6f, 30, 70.9f, 50.3f, 30.7f, 70, 50.4f };
- double[] arrY2 = new double[10] { 40.5f, 80, 20.8f, 30.6f, 15, 30.9f, 20.3f, 60.7f, 50, 80.4f };
- // 标题
- string strTitle = "某工厂某产品月生产量图表";
- // X轴单位名称
- string strXUnitName = "月份";
- // Y周轴单位名称
- string strYUnitName = "单位(万)";
- // 第1条折线图例名称
- string strY1Name = "第1条折线";
- // 第2条折线图例名称
- string strY2Name = "第2条折线";
- // 返回绘制的折线图
- Graphics gph = null;
- ClassDrawing classDrawing = new ClassDrawing();
- classDrawing.drawLineGraphY2(ref bmap, ref iScaleX, ref iScaleY, ref arrX, ref arrY1, ref arrY2, ref strTitle, ref strXUnitName, ref strYUnitName, ref strY1Name, ref strY2Name, out gph);
- //输出到浏览器
- System.IO.MemoryStream ms = new System.IO.MemoryStream();
- bmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
- Response.ClearContent();
- Response.ContentType = "p_w_picpath/Gif";
- Response.BinaryWrite(ms.ToArray());
- gph.Dispose();
- bmap.Dispose();
- }
- }