2011-02-15 97 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); 

     } 
    } 
}