2011-02-15 96 views
0

我有一個「甜甜圈」的圖形路徑。GDIPlus漸變沿圓形GraphicsPath

我想沿該路徑繪製漸變,並控制顏色開始和結束時圓上給定的開始和結束角度。

這樣,

http://www.andresilvadesign.com/wp-content/uploads/2011/01/Gauge-icon-design.jpg

一個linearGradint只能去一個角,並沒有遵循的路徑正常。

PathGradientBrush似乎只是..一個圓形漸變? 我似乎無法找到一種方法,在C#中正確做到這一點#

任何幫助將不勝感激!

回答

0

你可以使用PathGradientBrush繪製一個完整的圓,然後掩蓋它,用圖像中的測量面或者背景色中的圓(和/或餅形楔)來表示嗎?

+0

我想我可以,但如何繪製一個完整的圓形幫助?即時通訊試圖讓梯度沿着它的邊緣,而不是從內部到外部? – Aviel 2011-02-15 16:26:09

0

我知道這是相當古老的,作者可能不再在意,但我已經搜索了網絡上的這個問題的答案,我找不到任何。

評論bobpowell.net/pgb.htm中的KeithS鏈接對我來說不起作用,因爲我無法找到一種方法來獲取用於繪製曲線的實際點數。 (請參閱段落「讓他們包圍」)

嘗試模擬色輪我因此編寫了此代碼: (我不是專業人士,任何提高代碼的建議都非常受歡迎 - 特別是我的邊緣是有點模糊)

這個想法是爲了產生一個看起來像甜甜圈的多邊形,爲從彩色貼圖插入的每個「頂點」和置於「虛擬」甜甜圈中心的白色中心顏色應用顏色。 (我使用doublebuffering,以避免閃爍)

List<PointF> drawDonut(float angleA, float angleB, float width, int controlPointCount, float scaling, float centerX, float centerY) 
    { 
     List<PointF> points = new List<PointF>(); 
     if (controlPointCount < 2) 
     { 
      throw (new ArgumentOutOfRangeException("controlPointCount", "controlPointCount must be >1")); 
     } 
     if (width <= 0 || width > 100) 
     { 
      throw (new ArgumentOutOfRangeException("width", "width must be comprised between ]0:100]")); 
     } 

     List<float> angles = new List<float>(); 

     for (int i = 0; i < controlPointCount; i++) 
     { 
      angles.Add(angleA + (angleB - angleA) * (float)i/((float)controlPointCount - 1.0f)); 
     } 

     for (int i = 0; i < angles.Count; i++) 
     { 
      points.Add(new PointF((float)Math.Cos(angles[i]) * scaling + centerX, (float)Math.Sin(angles[i]) * scaling + centerY)); 
     } 
     for (int i = 0; i < angles.Count; i++) 
     { 
      points.Add(new PointF(((100.0f - width)/100.0f * (float)Math.Cos(angles[angles.Count - 1 - i])) * scaling + centerX, ((100.0f - width)/100.0f * (float)Math.Sin(angles[angles.Count - 1 - i])) * scaling + centerY)); 
     } 

     return points; 
    } 


    private List<Color> pieColor(Color[] MainColors, float[] mainStops, float[] stops) 
    { 
     List<Color> resultColors = new List<Color>(); 
     int index = 0; 
     float percent; 

     if (MainColors.Length != mainStops.Length) 
     { 
      throw new Exception("number of MainColors and mainStops must be the same"); 
     } 


     if (MainColors.Length < 2) 
     { 
      for (int i = 0; i < stops.Length; i++) 
      { 
       resultColors.Add((MainColors.Length == 1) ? MainColors[0] : Color.White); 
      } 
     } 
     else 
     { 
      for (int i = 0; i < stops.Length; i++) 
      { 
       index = Array.FindIndex(mainStops, x => x > stops[i]); 
       if (index == 0) 
       { 
        resultColors.Add(MainColors[0]); 
       } 
       else 
       { 
        if (index == -1) 
        { 
         resultColors.Add(MainColors.Last()); 
        } 
        else 
        { 
         percent = (stops[i] - mainStops[index - 1])/(mainStops[index] - mainStops[index - 1]) * 100f; 
         resultColors.Add(alphaBlend(MainColors[index - 1], MainColors[index], percent)); 
        } 
       } 
      } 
     } 

     return resultColors; 
    } 

    private Color alphaBlend(Color color1, Color color2, float percent) 
    { 

     byte R = (byte)(((float)color1.R * (100f - percent)/100f) + ((float)color2.R * (percent)/100f)); 
     byte G = (byte)(((float)color1.G * (100f - percent)/100f) + ((float)color2.G * (percent)/100f)); 
     byte B = (byte)(((float)color1.B * (100f - percent)/100f) + ((float)color2.B * (percent)/100f)); 
     return Color.FromArgb(R, G, B); 
    } 

    private void Form1_Paint(object sender, PaintEventArgs e) 
    { 
     RectangleF rec = e.ClipRectangle; 
     float midx = rec.Width/2; 
     float midy = rec.Height/2; 
     float pieSize = (float)Math.Min(midx, midy) * 0.9f; 
     float pieWidth = 5f; 
     float angleA = -225; 
     float angleB = 45; 
     int nstops = (int)(Math.Abs(angleA - angleB)/5 + 1); 
     float[] stops; 

     stops = new float[nstops]; 

     for (int i = 0; i < stops.Length; i++) 
     { 
      stops[i] = i * 100f/(stops.Length - 1); 
     } 

     List<PointF> myDonut = drawDonut(angleA * (float)Math.PI/180f, angleB * (float)Math.PI/180f, pieWidth, nstops, pieSize, midx, midy); 

     List<Color> myColors = pieColor(new Color[] { Color.Red, Color.Yellow, Color.Green, Color.Cyan, Color.Blue, Color.Magenta, Color.Red }, 
             new float[] { 0.0f, 100f/6f, 200f/6f, 300f/6f, 400f/6f, 500f/6f, 600f/6f }, 
             stops); 

     Color[] myPieColor = new Color[myDonut.Count]; 

     for (int i = 0; i < (myPieColor.Length/2); i++) 
     { 
      myPieColor[i] = myColors[i]; 
      myPieColor[myPieColor.Length - i - 1] = myColors[i]; 
     } 

     GraphicsPath gp = new GraphicsPath(); 
     gp.AddLines(myDonut.ToArray()); 
     e.Graphics.SmoothingMode = SmoothingMode.HighQuality; 
     using (PathGradientBrush b = new PathGradientBrush(gp)) 
     { 
      b.CenterPoint = new PointF(midx, midy); 
      b.CenterColor = Color.White; 
      b.SurroundColors = myPieColor; 

      e.Graphics.FillPath(b, gp); 

     } 
    } 
}