用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的地址為上面的一般處理程序的相對網站地址


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM