Практическое руководство. Создание градиента вдоль контура

Класс PathGradientBrush позволяет выбрать способ заполнения фигуры постепенно сменяющимися цветами. Например, можно указать один цвет для центра пути, а другой — для его границы. Можно также указать отдельные цвета для нескольких выбранных точек вдоль границы пути.

Примечание.

В GDI+ путь — это последовательность линий и кривых, поддерживаемых объектом GraphicsPath. Дополнительные сведения о путях GDI+ см. в разделах Графические пути в GDI+ и Конструирование и рисование путей.

Примеры, приведенные в этой статье — это методы, вызываемые из обработчика событий элемента управления Paint.

Чтобы заполнить эллипс путем-градиентом

  • В следующем примере мы заполним эллипс градиентной кистью пути. В качестве центрального цвета задан синий, а для цвета границ — аквамариновый. На рисунке ниже показан эллипс с заливкой.

    Gradient Path fills an ellipse.

    По умолчанию кисть градиента пути не работает за пределами пути. Если вы используете кисть градиента пути для заполнения фигуры вне границы пути, область экрана за пределами пути заполнена не будет.

    На следующем рисунке показано, что происходит при изменении вызова Graphics.FillEllipse в следующем коде на e.Graphics.FillRectangle(pthGrBrush, 0, 10, 200, 40):

    Gradient Path extended beyond boundary of the path.

    public void FillEllipseWithPathGradient(PaintEventArgs e)
    {
        // Create a path that consists of a single ellipse.
        GraphicsPath path = new GraphicsPath();
        path.AddEllipse(0, 0, 140, 70);
    
        // Use the path to construct a brush.
        PathGradientBrush pthGrBrush = new PathGradientBrush(path);
    
        // Set the color at the center of the path to blue.
        pthGrBrush.CenterColor = Color.FromArgb(255, 0, 0, 255);
    
        // Set the color along the entire boundary
        // of the path to aqua.
        Color[] colors = { Color.FromArgb(255, 0, 255, 255) };
        pthGrBrush.SurroundColors = colors;
    
        e.Graphics.FillEllipse(pthGrBrush, 0, 0, 140, 70);
    }
    
    ' Create a path that consists of a single ellipse.
    Dim path As New GraphicsPath()
    path.AddEllipse(0, 0, 140, 70)
    
    ' Use the path to construct a brush.
    Dim pthGrBrush As New PathGradientBrush(path)
    
    ' Set the color at the center of the path to blue.
    pthGrBrush.CenterColor = Color.FromArgb(255, 0, 0, 255)
    
    ' Set the color along the entire boundary 
    ' of the path to aqua.
    Dim colors As Color() = {Color.FromArgb(255, 0, 255, 255)}
    pthGrBrush.SurroundColors = colors
    
    e.Graphics.FillEllipse(pthGrBrush, 0, 0, 140, 70)
    
    

    Предыдущий пример кода предназначен для работы с Windows Forms и требует PaintEventArgs, который является параметром PaintEventHandler.

Указание точек на границе

  • В следующем примере создается градиентная кисть пути, основанная на пути в форме звезды. Код задает свойство CenterColor, которое устанавливает красный цвет в центреоиде звезды. Затем код задает свойство SurroundColors, чтобы указать различные цвета (хранящиеся в массиве colors) в отдельных точках массива points. Последняя инструкция кода заполняет контур в форме звезды с помощью кисти градиента пути.

    public void ConstructBrushFromStarShapedPath(PaintEventArgs e)
    {
        // Put the points of a polygon in an array.
        Point[] points = {
           new Point(75, 0),
           new Point(100, 50),
           new Point(150, 50),
           new Point(112, 75),
           new Point(150, 150),
           new Point(75, 100),
           new Point(0, 150),
           new Point(37, 75),
           new Point(0, 50),
           new Point(50, 50)};
    
        // Use the array of points to construct a path.
        GraphicsPath path = new GraphicsPath();
        path.AddLines(points);
    
        // Use the path to construct a path gradient brush.
        PathGradientBrush pthGrBrush = new PathGradientBrush(path);
    
        // Set the color at the center of the path to red.
        pthGrBrush.CenterColor = Color.FromArgb(255, 255, 0, 0);
    
        // Set the colors of the points in the array.
        Color[] colors = {
           Color.FromArgb(255, 0, 0, 0),
           Color.FromArgb(255, 0, 255, 0),
           Color.FromArgb(255, 0, 0, 255),
           Color.FromArgb(255, 255, 255, 255),
           Color.FromArgb(255, 0, 0, 0),
           Color.FromArgb(255, 0, 255, 0),
           Color.FromArgb(255, 0, 0, 255),
           Color.FromArgb(255, 255, 255, 255),
           Color.FromArgb(255, 0, 0, 0),
           Color.FromArgb(255, 0, 255, 0)};
    
        pthGrBrush.SurroundColors = colors;
    
        // Fill the path with the path gradient brush.
        e.Graphics.FillPath(pthGrBrush, path);
    }
    
    ' Put the points of a polygon in an array.
    Dim points As Point() = { _
       New Point(75, 0), _
       New Point(100, 50), _
       New Point(150, 50), _
       New Point(112, 75), _
       New Point(150, 150), _
       New Point(75, 100), _
       New Point(0, 150), _
       New Point(37, 75), _
       New Point(0, 50), _
       New Point(50, 50)}
    
    ' Use the array of points to construct a path.
    Dim path As New GraphicsPath()
    path.AddLines(points)
    
    ' Use the path to construct a path gradient brush.
    Dim pthGrBrush As New PathGradientBrush(path)
    
    ' Set the color at the center of the path to red.
    pthGrBrush.CenterColor = Color.FromArgb(255, 255, 0, 0)
    
    ' Set the colors of the points in the array.
    Dim colors As Color() = { _
       Color.FromArgb(255, 0, 0, 0), _
       Color.FromArgb(255, 0, 255, 0), _
       Color.FromArgb(255, 0, 0, 255), _
       Color.FromArgb(255, 255, 255, 255), _
       Color.FromArgb(255, 0, 0, 0), _
       Color.FromArgb(255, 0, 255, 0), _
       Color.FromArgb(255, 0, 0, 255), _
       Color.FromArgb(255, 255, 255, 255), _
       Color.FromArgb(255, 0, 0, 0), _
       Color.FromArgb(255, 0, 255, 0)}
    
    pthGrBrush.SurroundColors = colors
    
    ' Fill the path with the path gradient brush.
    e.Graphics.FillPath(pthGrBrush, path)
    
  • В следующем примере рисуется градиент пути без объекта GraphicsPath в коде. Рассматриваемый в примере конструктор PathGradientBrush получает массив точек, но не требует объекта GraphicsPath. Обратите внимание, что PathGradientBrush используется для заполнения прямоугольника, а не пути. Прямоугольник больше, чем используемый для определения кисти закрытый путь, поэтому некоторые прямоугольники не окрашиваются кистью. На следующем рисунке показаны прямоугольник (обозначен пунктиром) и часть прямоугольника, окрашенная кистью градиента пути:

    Gradient portion painted by the path gradient brush.

    public void DrawPathGradentWthoutGraphicsPath(PaintEventArgs e)
    {
        // Construct a path gradient brush based on an array of points.
        PointF[] ptsF = {
           new PointF(0, 0),
           new PointF(160, 0),
           new PointF(160, 200),
           new PointF(80, 150),
           new PointF(0, 200)};
    
        PathGradientBrush pBrush = new PathGradientBrush(ptsF);
    
        // An array of five points was used to construct the path gradient
        // brush. Set the color of each point in that array.
        Color[] colors = {
           Color.FromArgb(255, 255, 0, 0),  // (0, 0) red
           Color.FromArgb(255, 0, 255, 0),  // (160, 0) green
           Color.FromArgb(255, 0, 255, 0),  // (160, 200) green
           Color.FromArgb(255, 0, 0, 255),  // (80, 150) blue
           Color.FromArgb(255, 255, 0, 0)}; // (0, 200) red
    
        pBrush.SurroundColors = colors;
    
        // Set the center color to white.
        pBrush.CenterColor = Color.White;
    
        // Use the path gradient brush to fill a rectangle.
        e.Graphics.FillRectangle(pBrush, new Rectangle(0, 0, 160, 200));
    }
    
    ' Construct a path gradient brush based on an array of points.
    Dim ptsF As PointF() = { _
       New PointF(0, 0), _
       New PointF(160, 0), _
       New PointF(160, 200), _
       New PointF(80, 150), _
       New PointF(0, 200)}
    
    Dim pBrush As New PathGradientBrush(ptsF)
    
    ' An array of five points was used to construct the path gradient
    ' brush. Set the color of each point in that array.  
    'Point (0, 0) is red
    'Point (160, 0) is green
    'Point (160, 200) is green
    'Point (80, 150) is blue
    'Point (0, 200) is red
    Dim colors As Color() = { _
       Color.FromArgb(255, 255, 0, 0), _
       Color.FromArgb(255, 0, 255, 0), _
       Color.FromArgb(255, 0, 255, 0), _
       Color.FromArgb(255, 0, 0, 255), _
       Color.FromArgb(255, 255, 0, 0)}
    pBrush.SurroundColors = colors
    
    ' Set the center color to white.
    pBrush.CenterColor = Color.White
    
    ' Use the path gradient brush to fill a rectangle.
    e.Graphics.FillRectangle(pBrush, New Rectangle(0, 0, 160, 200))
    

Настройка градиента пути

  • Одним из способов настройки кисти градиента пути является установка его свойства FocusScales. Масштаб фокуса определяет внутренний путь, находящийся внутри основного пути. Цвет для центра отображается везде внутри данного внутреннего пути, а не только в центральной точке.

    В следующем примере создается кисть градиента пути на основе пути в форме эллипса. Код задает цвет границы синим, цвет центра — аквамариновым, а затем использует кисть градиента пути для заполнения пути в форме эллипса.

    Затем код задает масштаб фокуса кисти градиента пути. Для шкалы фокуса x задано значение 0,3, а для y — 0,8. Код вызывает метод TranslateTransform объекта Graphics, чтобы последующий вызов FillPath заполнял эллипс, находящийся справа от первого эллипса.

    Чтобы понять как работает масштабирование фокуса, представьте себе небольшой эллипс, центр которого совпадает с центром основного эллипса. Малый (внутренний) эллипс масштабируется (примерно по центру) горизонтально на коэффициент 0,3 и вертикально на коэффициент 0,8 от размеров главного эллипса. При переходе от границы внешнего эллипса к границе внутреннего цвет постепенно меняется от синего до аквамаринового. При переходе от границы внутреннего эллипса к общему центру цвет остается аквамариновым.

    На рисунке ниже показан результат выполнения кода. Эллипс слева окрашен аквамариновым цветом только в центральной точке. Эллипс справа окрашен аквамариновым везде внутри внутреннего пути.

Gradient effect of focus scales

public void CustomizePathGradientBrush(PaintEventArgs e)
{
    // Create a path that consists of a single ellipse.
    GraphicsPath path = new GraphicsPath();
    path.AddEllipse(0, 0, 200, 100);

    // Create a path gradient brush based on the elliptical path.
    PathGradientBrush pthGrBrush = new PathGradientBrush(path);

    // Set the color along the entire boundary to blue.
    Color[] color = { Color.Blue };
    pthGrBrush.SurroundColors = color;

    // Set the center color to aqua.
    pthGrBrush.CenterColor = Color.Aqua;

    // Use the path gradient brush to fill the ellipse.
    e.Graphics.FillPath(pthGrBrush, path);

    // Set the focus scales for the path gradient brush.
    pthGrBrush.FocusScales = new PointF(0.3f, 0.8f);

    // Use the path gradient brush to fill the ellipse again.
    // Show this filled ellipse to the right of the first filled ellipse.
    e.Graphics.TranslateTransform(220.0f, 0.0f);
    e.Graphics.FillPath(pthGrBrush, path);
}
' Create a path that consists of a single ellipse.
Dim path As New GraphicsPath()
path.AddEllipse(0, 0, 200, 100)

' Create a path gradient brush based on the elliptical path.
Dim pthGrBrush As New PathGradientBrush(path)

' Set the color along the entire boundary to blue.
' Changed variable name from color
Dim blueColor As Color() = {Color.Blue}
pthGrBrush.SurroundColors = blueColor

' Set the center color to aqua.
pthGrBrush.CenterColor = Color.Aqua

' Use the path gradient brush to fill the ellipse. 
e.Graphics.FillPath(pthGrBrush, path)

' Set the focus scales for the path gradient brush.
pthGrBrush.FocusScales = New PointF(0.3F, 0.8F)

' Use the path gradient brush to fill the ellipse again.
' Show this filled ellipse to the right of the first filled ellipse.
e.Graphics.TranslateTransform(220.0F, 0.0F)
e.Graphics.FillPath(pthGrBrush, path)

Настройка с помощью интерполяции

  • Настроить кисть градиента пути также можно через указание массива цветов интерполяции и массива позиций интерполяции.

    В следующем примере создается кисть градиента пути на основе пути в форме треугольника. Код задает свойство InterpolationColors кисти градиента пути, чтобы указать массив цветов интерполяции (темно-зеленый, аквамариновый, синий) и массив позиций интерполяции (0, 0,25, 1). При переходе от границы треугольника к центральной точке цвет постепенно переходит от темно-зеленого к аквамариновому, а затем от аквамаринового к синему. Изменение с темно-зеленого на аквамариновый происходит на расстоянии, составляющем 25 процентов расстояния от темно-зеленого до синего.

    На следующем рисунке показан треугольник, заполненный пользовательской кистью градиента пути.

    Triangle filled with custom path gradient brush.

    public void CustomizeWithInterpolation(PaintEventArgs e)
    {
        // Vertices of the outer triangle
        Point[] points = {
           new Point(100, 0),
           new Point(200, 200),
           new Point(0, 200)};
    
        // No GraphicsPath object is created. The PathGradientBrush
        // object is constructed directly from the array of points.
        PathGradientBrush pthGrBrush = new PathGradientBrush(points);
    
        Color[] colors = {
           Color.FromArgb(255, 0, 128, 0),    // dark green
           Color.FromArgb(255, 0, 255, 255),  // aqua
           Color.FromArgb(255, 0, 0, 255)};   // blue
    
        float[] relativePositions = {
           0f,       // Dark green is at the boundary of the triangle.
           0.4f,     // Aqua is 40 percent of the way from the boundary
                     // to the center point.
           1.0f};    // Blue is at the center point.
    
        ColorBlend colorBlend = new ColorBlend();
        colorBlend.Colors = colors;
        colorBlend.Positions = relativePositions;
        pthGrBrush.InterpolationColors = colorBlend;
    
        // Fill a rectangle that is larger than the triangle
        // specified in the Point array. The portion of the
        // rectangle outside the triangle will not be painted.
        e.Graphics.FillRectangle(pthGrBrush, 0, 0, 200, 200);
    }
    
    ' Vertices of the outer triangle
    Dim points As Point() = { _
       New Point(100, 0), _
       New Point(200, 200), _
       New Point(0, 200)}
    
    ' No GraphicsPath object is created. The PathGradientBrush
    ' object is constructed directly from the array of points.
    Dim pthGrBrush As New PathGradientBrush(points)
    
    ' Create an array of colors containing dark green, aqua, and  blue.
    Dim colors As Color() = { _
       Color.FromArgb(255, 0, 128, 0), _
       Color.FromArgb(255, 0, 255, 255), _
       Color.FromArgb(255, 0, 0, 255)}
    
    ' Dark green is at the boundary of the triangle.
    ' Aqua is 40 percent of the way from the boundary to the center point.
    ' Blue is at the center point.
    Dim relativePositions As Single() = { _
       0.0F, _
       0.4F, _
       1.0F}
    
    Dim colorBlend As New ColorBlend()
    colorBlend.Colors = colors
    colorBlend.Positions = relativePositions
    pthGrBrush.InterpolationColors = colorBlend
    
    ' Fill a rectangle that is larger than the triangle
    ' specified in the Point array. The portion of the
    ' rectangle outside the triangle will not be painted.
    e.Graphics.FillRectangle(pthGrBrush, 0, 0, 200, 200)
    
    

Установка центральной точки

  • По умолчанию центральная точка кисти градиента пути находится в центроиде пути, используемом для создания кисти. Расположение центральной точки можно изменить, задав свойство CenterPoint класса PathGradientBrush.

    В следующем примере создается кисть градиента пути на основе пути в форме эллипса. Центр эллипса находится в точке (70, 35), но центральная точка кисти градиента пути находится в координатах (120, 40).

    public void SetCenterPoint(PaintEventArgs e)
    {
        // Create a path that consists of a single ellipse.
        GraphicsPath path = new GraphicsPath();
        path.AddEllipse(0, 0, 140, 70);
    
        // Use the path to construct a brush.
        PathGradientBrush pthGrBrush = new PathGradientBrush(path);
    
        // Set the center point to a location that is not
        // the centroid of the path.
        pthGrBrush.CenterPoint = new PointF(120, 40);
    
        // Set the color at the center of the path to blue.
        pthGrBrush.CenterColor = Color.FromArgb(255, 0, 0, 255);
    
        // Set the color along the entire boundary
        // of the path to aqua.
        Color[] colors = { Color.FromArgb(255, 0, 255, 255) };
        pthGrBrush.SurroundColors = colors;
    
        e.Graphics.FillEllipse(pthGrBrush, 0, 0, 140, 70);
    }
    
    ' Create a path that consists of a single ellipse.
    Dim path As New GraphicsPath()
    path.AddEllipse(0, 0, 140, 70)
    
    ' Use the path to construct a brush.
    Dim pthGrBrush As New PathGradientBrush(path)
    
    ' Set the center point to a location that is not
    ' the centroid of the path.
    pthGrBrush.CenterPoint = New PointF(120, 40)
    
    ' Set the color at the center of the path to blue.
    pthGrBrush.CenterColor = Color.FromArgb(255, 0, 0, 255)
    
    ' Set the color along the entire boundary 
    ' of the path to aqua.
    Dim colors As Color() = {Color.FromArgb(255, 0, 255, 255)}
    pthGrBrush.SurroundColors = colors
    
    e.Graphics.FillEllipse(pthGrBrush, 0, 0, 140, 70)
    

    На следующем рисунке показаны заполненный эллипс и центральная точка кисти градиента пути:

    Gradient Path with filled ellipse and center point.

  • Центральную точку кисти градиента пути можно установить в координаты за пределами пути, используемого для создания кисти. В следующем примере выполняется замена вызова для задания свойства CenterPoint в предыдущем коде.

    public void SetCenterPointOutsidePath(PaintEventArgs e)
    {
        // Create a path that consists of a single ellipse.
        GraphicsPath path = new GraphicsPath();
        path.AddEllipse(0, 0, 140, 70);
    
        // Use the path to construct a brush.
        PathGradientBrush pthGrBrush = new PathGradientBrush(path);
    
        // Set the center point to a location that is not
        // the centroid of the path.
        pthGrBrush.CenterPoint = new PointF(145, 35);
    
        // Set the color at the center of the path to blue.
        pthGrBrush.CenterColor = Color.FromArgb(255, 0, 0, 255);
    
        // Set the color along the entire boundary
        // of the path to aqua.
        Color[] colors = { Color.FromArgb(255, 0, 255, 255) };
        pthGrBrush.SurroundColors = colors;
    
        e.Graphics.FillEllipse(pthGrBrush, 0, 0, 140, 70);
    }
    
    pthGrBrush.CenterPoint = New PointF(145, 35)
    

    На следующем рисунке показан достигнутый этой заменой результат:

    Gradient Path with center point outside the path.

    На предыдущем рисунке точки в крайнем правом углу эллипса не окрашены чистым синим цветом (хотя выглядят очень близко к нему). Цвета в градиенте расположены так, как если бы заливка достигла точки (145, 35), где цвет должен быть чисто синим (0, 0, 255). Но заливка никогда не достигает (145, 35), потому что градиентная кисть пути красит только внутри ее пути.

Компиляция кода

Предыдущий пример предназначен для работы с Windows Forms, и для него необходим параметр PaintEventArgse, передаваемый обработчику событий Paint.

См. также