16
2012
07

用c#画饼图和条形图,做数据统计

先上效果图:

饼图:

条形图:

通过在网上找资料,自己稍微整理下,注释配代码如下:

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的地址为上面的一般处理程序的相对网站地址

« 上一篇下一篇 »

评论列表:

1.我的名字叫麒  2012/7/16 13:00:12 回复该留言
消灭0回复
看了博主好像是用C#做C/S开发

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。