欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#绘制曲线图的方法

程序员文章站 2022-06-09 10:29:39
本文实例讲述了c#绘制曲线图的方法。分享给大家供大家参考。具体如下: 1. 曲线图效果: 2. c#代码: /// //...

本文实例讲述了c#绘制曲线图的方法。分享给大家供大家参考。具体如下:

1. 曲线图效果:

C#绘制曲线图的方法

2. c#代码:

/// <summary>
/// 自动根据参数调整图像大小
/// </summary>
public void fit()
{
 //计算字体距离
 intfontspace = fontsize + 5;
 //计算图像边距
 float fltspace = math.min(width / 6, height / 6);
 xspace = fltspace;
 yspace = fltspace;
 //计算x轴刻度宽度
 xslice = (width - 2 * xspace) / (keys.length - 1);
 //计算y轴刻度宽度和y轴刻度开始值
 float fltminvalue = 0;
 float fltmaxvalue = 0;
 for (int i = 0; i < values.length; i++)
 {
  if (values[i] < fltminvalue)
  {
  fltminvalue = values[i];
  }
  else if (values[i] > fltmaxvalue)
  {
  fltmaxvalue = values[i];
  }
 }
 if (yslicebegin > fltminvalue)
 {
  yslicebegin = fltminvalue;
 }
 int intyslicecount = (int)(fltmaxvalue / yslicevalue);
 if (fltmaxvalue % yslicevalue != 0)
 {
  intyslicecount++;
 }
 yslice = (height - 2 * yspace) / intyslicecount;
}

3. 数据缩小一个级别的效果:

C#绘制曲线图的方法

4. 完整代码 drawingcurve.cs:

using system;
using system.collections.generic;
using system.text;
using system.drawing;
using system.data;
using system.drawing.drawing2d;
namespace sarchpms.business.draw
{
 public class drawingcurve : drawingchart
 {
  /// <summary>
  /// 画曲线图
  /// </summary>
  /// <param name="dsparameter"></param>
  /// <returns></returns>
  public override bitmap drawimage(dataset dsparameter)
  {
   curve2d cuv2d = new curve2d();
   cuv2d.fit();
   return cuv2d.createimage();
  }
 }
 public class curve2d
 {
  private graphics objgraphics; //graphics 类提供将对象绘制到显示设备的方法
  private bitmap objbitmap; //位图对象
  private float fltwidth = 480; //图像宽度
  private float fltheight = 248; //图像高度
  private float fltxslice = 50; //x轴刻度宽度
  private float fltyslice = 50; //y轴刻度宽度
  private float fltyslicevalue = 20; //y轴刻度的数值宽度
  private float fltyslicebegin = 0; //y轴刻度开始值
  private float flttension = 0.5f;
  private string strtitle = "曲线图"; //标题
  private string strxaxistext = "月份"; //x轴说明文字
  private string stryaxistext = "万元"; //y轴说明文字
  private string[] strskeys = new string[] { "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月" }; //键
  private float[] fltsvalues = new float[] { 20.0f, 30.0f, 50.0f, 55.4f, 21.6f, 12.8f, 99.5f, 36.4f, 78.2f, 56.4f, 45.8f, 66.5f, 99.5f, 36.4f, 78.2f, 56.4f, 45.8f, 66.5f, 20.0f, 30.0f, 50.0f, 55.4f, 21.6f, 12.8f }; //值
  private color clrbgcolor = color.snow; //背景色
  private color clrtextcolor = color.black; //文字颜色
  private color clrbordercolor = color.black; //整体边框颜色
  private color clraxiscolor = color.black; //轴线颜色
  private color clraxistextcolor = color.black; //轴说明文字颜色
  private color clrslicetextcolor = color.black; //刻度文字颜色
  private color clrslicecolor = color.black; //刻度颜色
  private color[] clrscurvecolors = new color[] { color.red, color.blue }; //曲线颜色
  private float fltxspace = 100f; //图像左右距离边缘距离
  private float fltyspace = 100f; //图像上下距离边缘距离
  private int intfontsize = 9; //字体大小号数
  private float fltxrotateangle = 30f; //x轴文字旋转角度
  private float fltyrotateangle = 0f; //y轴文字旋转角度
  private int intcurvesize = 2; //曲线线条大小
  private int intfontspace = 0; //intfontspace 是字体大小和距离调整出来的一个比较适合的数字
  #region 公共属性
  /// <summary>
  /// 图像的宽度
  /// </summary>
  public float width
  {
   set
   {
    if (value < 100)
    {
     fltwidth = 100;
    }
    else
    {
     fltwidth = value;
    }
   }
   get
   {
    if (fltwidth <= 100)
    {
     return 100;
    }
    else
    {
     return fltwidth;
    }
   }
  }
  /// <summary>
  /// 图像的高度
  /// </summary>
  public float height
  {
   set
   {
    if (value < 100)
    {
     fltheight = 100;
    }
    else
    {
     fltheight = value;
    }
   }
   get
   {
    if (fltheight <= 100)
    {
     return 100;
    }
    else
    {
     return fltheight;
    }
   }
  }
  /// <summary>
  /// x轴刻度宽度
  /// </summary>
  public float xslice
  {
   set { fltxslice = value; }
   get { return fltxslice; }
  }
  /// <summary>
  /// y轴刻度宽度
  /// </summary>
  public float yslice
  {
   set { fltyslice = value; }
   get { return fltyslice; }
  }
  /// <summary>
  /// y轴刻度的数值宽度
  /// </summary>
  public float yslicevalue
  {
   set { fltyslicevalue = value; }
   get { return fltyslicevalue; }
  }
  /// <summary>
  /// y轴刻度开始值
  /// </summary>
  public float yslicebegin
  {
   set { fltyslicebegin = value; }
   get { return fltyslicebegin; }
  }
  /// <summary>
  /// 张力系数
  /// </summary>
  public float tension
  {
   set
   {
    if (value < 0.0f && value > 1.0f)
    {
     flttension = 0.5f;
    }
    else
    {
     flttension = value;
    }
   }
   get
   {
    return flttension;
   }
  }
  /// <summary>
  /// 标题
  /// </summary>
  public string title
  {
   set { strtitle = value; }
   get { return strtitle; }
  }
  /// <summary>
  /// 键,x轴数据
  /// </summary>
  public string[] keys
  {
   set { strskeys = value; }
   get { return strskeys; }
  }
  /// <summary>
  /// 值,y轴数据
  /// </summary>
  public float[] values
  {
   set { fltsvalues = value; }
   get { return fltsvalues; }
  }
  /// <summary>
  /// 背景色
  /// </summary>
  public color bgcolor
  {
   set { clrbgcolor = value; }
   get { return clrbgcolor; }
  }
  /// <summary>
  /// 文字颜色
  /// </summary>
  public color textcolor
  {
   set { clrtextcolor = value; }
   get { return clrtextcolor; }
  }
  /// <summary>
  /// 整体边框颜色
  /// </summary>
  public color bordercolor
  {
   set { clrbordercolor = value; }
   get { return clrbordercolor; }
  }
  /// <summary>
  /// 轴线颜色
  /// </summary>
  public color axiscolor
  {
   set { clraxiscolor = value; }
   get { return clraxiscolor; }
  }
  /// <summary>
  /// x轴说明文字
  /// </summary>
  public string xaxistext
  {
   set { strxaxistext = value; }
   get { return strxaxistext; }
  }
  /// <summary>
  /// y轴说明文字
  /// </summary>
  public string yaxistext
  {
   set { stryaxistext = value; }
   get { return stryaxistext; }
  }
  /// <summary>
  /// 轴说明文字颜色
  /// </summary>
  public color axistextcolor
  {
   set { clraxistextcolor = value; }
   get { return clraxistextcolor; }
  }
  /// <summary>
  /// 刻度文字颜色
  /// </summary>
  public color slicetextcolor
  {
   set { clrslicetextcolor = value; }
   get { return clrslicetextcolor; }
  }
  /// <summary>
  /// 刻度颜色
  /// </summary>
  public color slicecolor
  {
   set { clrslicecolor = value; }
   get { return clrslicecolor; }
  }
  /// <summary>
  /// 曲线颜色
  /// </summary>
  public color[] curvecolors
  {
   set { clrscurvecolors = value; }
   get { return clrscurvecolors; }
  }
  /// <summary>
  /// x轴文字旋转角度
  /// </summary>
  public float xrotateangle
  {
   get { return fltxrotateangle; }
   set { fltxrotateangle = value; }
  }
  /// <summary>
  /// y轴文字旋转角度
  /// </summary>
  public float yrotateangle
  {
   get { return fltyrotateangle; }
   set { fltyrotateangle = value; }
  }
  /// <summary>
  /// 图像左右距离边缘距离
  /// </summary>
  public float xspace
  {
   get { return fltxspace; }
   set { fltxspace = value; }
  }
  /// <summary>
  /// 图像上下距离边缘距离
  /// </summary>
  public float yspace
  {
   get { return fltyspace; }
   set { fltyspace = value; }
  }
  /// <summary>
  /// 字体大小号数
  /// </summary>
  public int fontsize
  {
   get { return intfontsize; }
   set { intfontsize = value; }
  }
  /// <summary>
  /// 曲线线条大小
  /// </summary>
  public int curvesize
  {
   get { return intcurvesize; }
   set { intcurvesize = value; }
  }
  #endregion
  /// <summary>
  /// 自动根据参数调整图像大小
  /// </summary>
  public void fit()
  {
   //计算字体距离
   intfontspace = fontsize + 5;
   //计算图像边距
   float fltspace = math.min(width / 6, height / 6);
   xspace = fltspace;
   yspace = fltspace;
   //计算x轴刻度宽度
   xslice = (width - 2 * xspace) / (keys.length - 1);
   //计算y轴刻度宽度和y轴刻度开始值
   float fltminvalue = 0;
   float fltmaxvalue = 0;
   for (int i = 0; i < values.length; i++)
   {
    if (values[i] < fltminvalue)
    {
     fltminvalue = values[i];
    }
    else if (values[i] > fltmaxvalue)
    {
     fltmaxvalue = values[i];
    }
   }
   if (yslicebegin > fltminvalue)
   {
    yslicebegin = fltminvalue;
   }
   int intyslicecount = (int)(fltmaxvalue / yslicevalue);
   if (fltmaxvalue % yslicevalue != 0)
   {
    intyslicecount++;
   }
   yslice = (height - 2 * yspace) / intyslicecount;
  }
  /// <summary>
  /// 生成图像并返回bmp图像对象
  /// </summary>
  /// <returns></returns>
  public bitmap createimage()
  {
   initializegraph();
   int intkeyscount = keys.length;
   int intvaluescount = values.length;
   if (intvaluescount % intkeyscount == 0)
   {
    int intcurvescount = intvaluescount / intkeyscount;
    for (int i = 0; i < intcurvescount; i++)
    {
     float[] fltcurrentvalues = new float[intkeyscount];
     for (int j = 0; j < intkeyscount; j++)
     {
      fltcurrentvalues[j] = values[i * intkeyscount + j];
     }
     drawcontent(ref objgraphics, fltcurrentvalues, clrscurvecolors[i]);
    }
   }
   else
   {
    objgraphics.drawstring("发生错误,values的长度必须是keys的整数倍!", new font("宋体", fontsize + 5), new solidbrush(textcolor), new point((int)xspace, (int)(height / 2)));
   }
   return objbitmap;
  }
  /// <summary>
  /// 初始化和填充图像区域,画出边框,初始标题
  /// </summary>
  private void initializegraph()
  {
   //根据给定的高度和宽度创建一个位图图像
   objbitmap = new bitmap((int)width, (int)height);
   //从指定的 objbitmap 对象创建 objgraphics 对象 (即在objbitmap对象中画图)
   objgraphics = graphics.fromimage(objbitmap);
   //根据给定颜色(lightgray)填充图像的矩形区域 (背景)
   objgraphics.drawrectangle(new pen(bordercolor, 1), 0, 0, width - 1, height - 1); //画边框
   objgraphics.fillrectangle(new solidbrush(bgcolor), 1, 1, width - 2, height - 2); //填充边框
   //画x轴,注意图像的原始x轴和y轴计算是以左上角为原点,向右和向下计算的
   float fltx1 = xspace;
   float flty1 = height - yspace;
   float fltx2 = width - xspace + xslice / 2;
   float flty2 = flty1;
   objgraphics.drawline(new pen(new solidbrush(axiscolor), 1), fltx1, flty1, fltx2, flty2);
   //画y轴
   fltx1 = xspace;
   flty1 = height - yspace;
   fltx2 = xspace;
   flty2 = yspace - yslice / 2;
   objgraphics.drawline(new pen(new solidbrush(axiscolor), 1), fltx1, flty1, fltx2, flty2);
   //初始化轴线说明文字
   setaxistext(ref objgraphics);
   //初始化x轴上的刻度和文字
   setxaxis(ref objgraphics);
   //初始化y轴上的刻度和文字
   setyaxis(ref objgraphics);
   //初始化标题
   createtitle(ref objgraphics);
  }
  /// <summary>
  /// 初始化轴线说明文字
  /// </summary>
  /// <param name="objgraphics"></param>
  private void setaxistext(ref graphics objgraphics)
  {
   float fltx = width - xspace + xslice / 2 - (xaxistext.length - 1) * intfontspace;
   float flty = height - yspace - intfontspace;
   objgraphics.drawstring(xaxistext, new font("宋体", fontsize), new solidbrush(axistextcolor), fltx, flty);
   fltx = xspace + 5;
   flty = yspace - yslice / 2 - intfontspace;
   for (int i = 0; i < yaxistext.length; i++)
   {
    objgraphics.drawstring(yaxistext[i].tostring(), new font("宋体", fontsize), new solidbrush(axistextcolor), fltx, flty);
    flty += intfontspace; //字体上下距离
   }
  }
  /// <summary>
  /// 初始化x轴上的刻度和文字
  /// </summary>
  /// <param name="objgraphics"></param>
  private void setxaxis(ref graphics objgraphics)
  {
   float fltx1 = xspace;
   float flty1 = height - yspace;
   float fltx2 = xspace;
   float flty2 = height - yspace;
   int icount = 0;
   int islicecount = 1;
   float scale = 0;
   float iwidth = ((width - 2 * xspace) / xslice) * 50; //将要画刻度的长度分段,并乘以50,以10为单位画刻度线。
   float fltsliceheight = xslice / 10; //刻度线的高度
   objgraphics.translatetransform(fltx1, flty1); //平移图像(原点)
   objgraphics.rotatetransform(xrotateangle, matrixorder.prepend); //旋转图像
   objgraphics.drawstring(keys[0].tostring(), new font("宋体", fontsize), new solidbrush(slicetextcolor), 0, 0);
   objgraphics.resettransform(); //重置图像
   for (int i = 0; i <= iwidth; i += 10) //以10为单位
   {
    scale = i * xslice / 50;//即(i / 10) * (xslice / 5),将每个刻度分五部分画,但因为i以10为单位,得除以10
    if (icount == 5)
    {
     objgraphics.drawline(new pen(new solidbrush(axiscolor)), fltx1 + scale, flty1 + fltsliceheight * 1.5f, fltx2 + scale, flty2 - fltsliceheight * 1.5f);
     //画网格虚线
     pen pendashed = new pen(new solidbrush(axiscolor));
     pendashed.dashstyle = dashstyle.dash;
     objgraphics.drawline(pendashed, fltx1 + scale, flty1, fltx2 + scale, yspace - yslice / 2);
     //这里显示x轴刻度
     if (islicecount <= keys.length - 1)
     {
      objgraphics.translatetransform(fltx1 + scale, flty1);
      objgraphics.rotatetransform(xrotateangle, matrixorder.prepend);
      objgraphics.drawstring(keys[islicecount].tostring(), new font("宋体", fontsize), new solidbrush(slicetextcolor), 0, 0);
      objgraphics.resettransform();
     }
     else
     {
      //超过范围,不画任何刻度文字
     }
     icount = 0;
     islicecount++;
     if (fltx1 + scale > width - xspace)
     {
      break;
     }
    }
    else
    {
     objgraphics.drawline(new pen(new solidbrush(slicecolor)), fltx1 + scale, flty1 + fltsliceheight, fltx2 + scale, flty2 - fltsliceheight);
    }
    icount++;
   }
  }
  /// <summary>
  /// 初始化y轴上的刻度和文字
  /// </summary>
  /// <param name="objgraphics"></param>
  private void setyaxis(ref graphics objgraphics)
  {
   float fltx1 = xspace;
   float flty1 = height - yspace;
   float fltx2 = xspace;
   float flty2 = height - yspace;
   int icount = 0;
   float scale = 0;
   int islicecount = 1;
   float iheight = ((height - 2 * yspace) / yslice) * 50; //将要画刻度的长度分段,并乘以50,以10为单位画刻度线。
   float fltslicewidth = yslice / 10; //刻度线的宽度
   string strslicetext = string.empty;
   objgraphics.translatetransform(xspace - intfontspace * yslicebegin.tostring().length, height - yspace); //平移图像(原点)
   objgraphics.rotatetransform(yrotateangle, matrixorder.prepend); //旋转图像
   objgraphics.drawstring(yslicebegin.tostring(), new font("宋体", fontsize), new solidbrush(slicetextcolor), 0, 0);
   objgraphics.resettransform(); //重置图像
   for (int i = 0; i < iheight; i += 10)
   {
    scale = i * yslice / 50; //即(i / 10) * (yslice / 5),将每个刻度分五部分画,但因为i以10为单位,得除以10
    if (icount == 5)
    {
     objgraphics.drawline(new pen(new solidbrush(axiscolor)), fltx1 - fltslicewidth * 1.5f, flty1 - scale, fltx2 + fltslicewidth * 1.5f, flty2 - scale);
     //画网格虚线
     pen pendashed = new pen(new solidbrush(axiscolor));
     pendashed.dashstyle = dashstyle.dash;
     objgraphics.drawline(pendashed, xspace, flty1 - scale, width - xspace + xslice / 2, flty2 - scale);
     //这里显示y轴刻度
     strslicetext = convert.tostring(yslicevalue * islicecount + yslicebegin);
     objgraphics.translatetransform(xspace - intfontsize * strslicetext.length, flty1 - scale); //平移图像(原点)
     objgraphics.rotatetransform(yrotateangle, matrixorder.prepend); //旋转图像
     objgraphics.drawstring(strslicetext, new font("宋体", fontsize), new solidbrush(slicetextcolor), 0, 0);
     objgraphics.resettransform(); //重置图像
     icount = 0;
     islicecount++;
    }
    else
    {
     objgraphics.drawline(new pen(new solidbrush(slicecolor)), fltx1 - fltslicewidth, flty1 - scale, fltx2 + fltslicewidth, flty2 - scale);
    }
    icount++;
   }
  }
  /// <summary>
  /// 画曲线
  /// </summary>
  /// <param name="objgraphics"></param>
  private void drawcontent(ref graphics objgraphics, float[] fltcurrentvalues, color clrcurrentcolor)
  {
   pen curvepen = new pen(clrcurrentcolor, curvesize);
   pointf[] curvepointf = new pointf[keys.length];
   float keys = 0;
   float values = 0;
   for (int i = 0; i < keys.length; i++)
   {
    keys = xslice * i + xspace;
    values = (height - yspace) + yslicebegin - yslice * (fltcurrentvalues[i] / yslicevalue);
    curvepointf[i] = new pointf(keys, values);
   }
   objgraphics.drawcurve(curvepen, curvepointf, tension);
  }
  /// <summary>
  /// 初始化标题
  /// </summary>
  /// <param name="objgraphics"></param>
  private void createtitle(ref graphics objgraphics)
  {
   objgraphics.drawstring(title, new font("宋体", fontsize), new solidbrush(textcolor), new point((int)(width - xspace) - intfontsize * title.length, (int)(yspace - yslice / 2 - intfontspace)));
  }
 }
}

希望本文所述对大家的c#程序设计有所帮助。