Criando um Gradiente de Caminho

A classe PathGradientBrush permite personalizar a maneira como você preenche uma forma com cores que mudam gradualmente. Um objeto PathGradientBrush tem um caminho de limite e um ponto central. Você pode especificar uma cor para o ponto central e outra cor para o limite. Você também pode especificar cores separadas para cada um dos vários pontos ao longo do limite.

Note

No GDI+, um caminho é uma sequência de linhas e curvas mantidas por um objeto GraphicsPath . Para obter mais informações sobre caminhos GDI+, consulte Caminhos e Construção e Caminhos de Desenho.

 

O exemplo a seguir preenche uma elipse com pincel de gradiente de caminho. A cor central é definida como azul e a cor de limite é definida como aqua.

// Create a path that consists of a single ellipse.
GraphicsPath path;
path.AddEllipse(0, 0, 140, 70);

// Use the path to construct a brush.
PathGradientBrush pthGrBrush(&path);

// Set the color at the center of the path to blue.
pthGrBrush.SetCenterColor(Color(255, 0, 0, 255));

// Set the color along the entire boundary of the path to aqua.
Color colors[] = {Color(255, 0, 255, 255)};
int count = 1;
pthGrBrush.SetSurroundColors(colors, &count);

graphics.FillEllipse(&pthGrBrush, 0, 0, 140, 70);

A ilustração a seguir mostra a elipse preenchida.

ilustração mostrando uma elipse com um preenchimento de gradiente

Por padrão, um pincel de gradiente de caminho não é estendido para fora do limite do caminho. Se você usar o pincel de gradiente de caminho para preencher uma forma que se estende para além do limite do caminho, a área da tela fora do caminho não será preenchida. A ilustração a seguir mostra o que acontece se você substituir a chamada Graphics::FillEllipse no código anterior por graphics.FillRectangle(&pthGrBrush, 0, 10, 200, 40).

ilustração mostrando uma fatia horizontal da elipse anterior

Especificando pontos no limite

O exemplo a seguir constrói um pincel de gradiente de caminho de um caminho em forma de estrela. O código chama o método PathGradientBrush::SetCenterColor para definir a cor no centroide da estrela como vermelho. Em seguida, o código chama o método PathGradientBrush::SetSurroundColors para especificar várias cores (armazenadas na matriz de cores ) nos pontos individuais da matriz de pontos . A instrução de código final preenche o caminho em forma de estrela com o pincel de gradiente de caminho.

// Put the points of a polygon in an array.
Point points[] = {Point(75, 0),    Point(100, 50), 
                  Point(150, 50),  Point(112, 75),
                  Point(150, 150), Point(75, 100), 
                  Point(0, 150),   Point(37, 75), 
                  Point(0, 50),    Point(50, 50)};

// Use the array of points to construct a path.
GraphicsPath path;
path.AddLines(points, 10);

// Use the path to construct a path gradient brush.
PathGradientBrush pthGrBrush(&path);

// Set the color at the center of the path to red.
pthGrBrush.SetCenterColor(Color(255, 255, 0, 0));

// Set the colors of the points in the array.
Color colors[] = {Color(255, 0, 0, 0),   Color(255, 0, 255, 0),
                  Color(255, 0, 0, 255), Color(255, 255, 255, 255), 
                  Color(255, 0, 0, 0),   Color(255, 0, 255, 0), 
                  Color(255, 0, 0, 255), Color(255, 255, 255, 255),
                  Color(255, 0, 0, 0),   Color(255, 0, 255, 0)};

int count = 10;
pthGrBrush.SetSurroundColors(colors, &count);

// Fill the path with the path gradient brush.
graphics.FillPath(&pthGrBrush, &path);

A ilustração a seguir mostra a estrela preenchida.

Ilustração mostrando uma estrela de cinco pontas que se enche de vermelho no centro a várias cores em cada ponto da estrela

O exemplo a seguir constrói um pincel de gradiente de trajetória com base em uma matriz de pontos. Uma cor é atribuída a cada um dos cinco pontos na matriz. Se você conectasse os cinco pontos por linhas retas, obteria um polígono de cinco lados. Uma cor também é atribuída ao centro (centroide) desse polígono — neste exemplo, o centro (80, 75) é definido como branco. A instrução de código final no exemplo preenche um retângulo com o pincel de gradiente de caminho.

A cor usada para preencher o retângulo é branca em (80, 75) e muda gradualmente à medida que você se afasta de (80, 75) em direção aos pontos na matriz. Por exemplo, à medida que você passa de (80, 75) para (0, 0), a cor muda gradualmente de branco para vermelho e, à medida que você passa de (80, 75) para (160, 0), a cor muda gradualmente de branco para verde.

// Construct a path gradient brush based on an array of points.
PointF ptsF[] = {PointF(0.0f, 0.0f), 
                 PointF(160.0f, 0.0f), 
                 PointF(160.0f, 200.0f),
                 PointF(80.0f, 150.0f),
                 PointF(0.0f, 200.0f)};

PathGradientBrush pBrush(ptsF, 5);

// 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(255, 255, 0, 0),  // (0, 0) red
                  Color(255, 0, 255, 0),  // (160, 0) green
                  Color(255, 0, 255, 0),  // (160, 200) green
                  Color(255, 0, 0, 255),  // (80, 150) blue
                  Color(255, 255, 0, 0)}; // (0, 200) red

int count = 5;
pBrush.SetSurroundColors(colors, &count);

// Set the center color to white.
pBrush.SetCenterColor(Color(255, 255, 255, 255));

// Use the path gradient brush to fill a rectangle.
graphics.FillRectangle(&pBrush, Rect(0, 0, 180, 220));

Observe que não há nenhum objeto GraphicsPath no código anterior. O construtor PathGradientBrush específico no exemplo recebe um ponteiro para uma matriz de pontos, mas não requer um objeto GraphicsPath . Além disso, observe que o pincel de gradiente de caminho é usado para preencher um retângulo, não um caminho. O retângulo é maior que o caminho usado para definir o pincel, portanto, parte do retângulo não é pintado pelo pincel. A ilustração a seguir mostra o retângulo (linha pontilhada) e a parte do retângulo pintado pelo pincel de gradiente de caminho.

ilustração mostrando um retângulo delimitado por uma linha pontilhada, parcialmente pintado por um gradiente multicolorido

Personalizando um Gradiente de Caminho

Uma maneira de personalizar um pincel de gradiente de caminho é definir suas escalas de foco. As escalas de foco especificam um caminho interno que está dentro do caminho principal. A cor central é exibida em todos os lugares dentro desse caminho interno, em vez de apenas no ponto central. Para definir as escalas de foco de um pincel de gradiente de caminho, chame o método PathGradientBrush::SetFocusScales.

O exemplo a seguir cria um pincel de gradiente de caminho com base em uma trajetória elíptica. O código define a cor do limite como azul, define a cor do centro para azul-piscina e, em seguida, usa o pincel de gradiente de caminho para preencher o caminho elíptico.

Em seguida, o código define as escalas de foco do pincel de gradiente de caminho. A escala de foco x é definida como 0,3 e a escala de foco y é definida como 0,8. O código chama o método Graphics::TranslateTransform de um objeto Graphics para que a chamada subsequente para Graphics::FillPath preencha uma elipse que fica à direita da primeira elipse.

Para ver o efeito das escalas de foco, imagine uma pequena elipse que compartilha seu centro com a elipse principal. A pequena elipse (interna) é a principal elipse dimensionada (sobre seu centro) horizontalmente por um fator de 0,3 e verticalmente por um fator de 0,8. À medida que você passa do limite da elipse externa para o limite da elipse interna, a cor muda gradualmente de azul para aqua. À medida que você passa do limite da elipse interna para o centro compartilhado, a cor permanece aqua.

// Create a path that consists of a single ellipse.
GraphicsPath path;
path.AddEllipse(0, 0, 200, 100);

// Create a path gradient brush based on the elliptical path.
PathGradientBrush pthGrBrush(&path);
pthGrBrush.SetGammaCorrection(TRUE);

// Set the color along the entire boundary to blue.
Color color(Color(255, 0, 0, 255));
INT num = 1;
pthGrBrush.SetSurroundColors(&color, &num);

// Set the center color to aqua.
pthGrBrush.SetCenterColor(Color(255, 0, 255, 255));
 
// Use the path gradient brush to fill the ellipse. 
graphics.FillPath(&pthGrBrush, &path);

// Set the focus scales for the path gradient brush.
pthGrBrush.SetFocusScales(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.
graphics.TranslateTransform(220.0f, 0.0f);
graphics.FillPath(&pthGrBrush, &path);

A ilustração a seguir mostra a saída do código anterior. A elipse à esquerda está na cor aqua somente no ponto central. A elipse à direita é azul-piscina em qualquer lugar dentro do caminho interno.

ilustração mostrando duas elipses que variam do verde-água ao azul: a primeira tem muito pouco verde-água; a segunda tem muito mais

Outra maneira de personalizar um pincel de gradiente de caminho é especificar uma matriz de cores de preset e uma matriz de posições de interpolação.

O exemplo a seguir cria um pincel de gradiente de caminho com base em um triângulo. O código chama o método PathGradientBrush::SetInterpolationColors do pincel de gradiente de caminho para especificar uma matriz de cores de interpolação (verde escuro, aqua, azul) e uma matriz de posições de interpolação (0, 0.25, 1). À medida que você passa do limite do triângulo para o ponto central, a cor muda gradualmente de verde escuro para aqua e, em seguida, de aqua para azul. A mudança de verde escuro para aqua acontece em 25% da distância de verde escuro para azul.

// Vertices of the triangle
Point points[] = {Point(100, 0), 
                  Point(200, 200), 
                  Point(0, 200)};

// No GraphicsPath object is created. The PathGradient
// brush is constructed directly from the array of points.
PathGradientBrush pthGrBrush(points, 3);

Color presetColors[] = {
   Color(255, 0, 128, 0),    // Dark green
   Color(255, 0, 255, 255),  // Aqua
   Color(255, 0, 0, 255)};   // Blue

REAL interpPositions[] = {
   0.0f,   // Dark green is at the boundary of the triangle.
   0.25f,  // Aqua is 25 percent of the way from the boundary
           // to the center point.
   1.0f};  // Blue is at the center point.
                  
pthGrBrush.SetInterpolationColors(presetColors, interpPositions, 3);

// 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.
graphics.FillRectangle(&pthGrBrush, 0, 0, 200, 200);

A ilustração a seguir mostra a saída do código anterior.

ilustração mostrando um triângulo que sombreia de azul no centro, para aqua, para verde nas bordas

Definindo o ponto central

Por padrão, o ponto central de um pincel de gradiente de caminho é o centroide de caminho usado para construir o pincel. Você pode alterar o local do ponto central chamando o método PathGradientBrush::SetCenterPoint da classe PathGradientBrush .

O exemplo a seguir cria um pincel de gradiente de caminho com base em uma elipse. O centro da elipse é em (70, 35), mas o ponto central do pincel de gradiente de caminho é definido como (120, 40).

// Create a path that consists of a single ellipse.
GraphicsPath path;
path.AddEllipse(0, 0, 140, 70);

// Use the path to construct a brush.
PathGradientBrush pthGrBrush(&path);

// Set the center point to a location that is not the centroid of the path.
pthGrBrush.SetCenterPoint(Point(120, 40));

// Set the color at the center point to blue.
pthGrBrush.SetCenterColor(Color(255, 0, 0, 255));

// Set the color along the entire boundary of the path to aqua.
Color colors[] = {Color(255, 0, 255, 255)};
int count = 1;
pthGrBrush.SetSurroundColors(colors, &count);

graphics.FillEllipse(&pthGrBrush, 0, 0, 140, 70);

A ilustração a seguir mostra a elipse preenchida e o ponto central do pincel de gradiente de caminho.

Ilustração mostrando uma elipse preenchida com um gradiente de azul para aqua, a partir de um ponto central próximo a uma das extremidades.

Você pode definir o ponto central de um pincel de gradiente de caminho para um local fora do caminho que foi usado para construir o pincel. No código anterior, se você substituir a chamada para PathGradientBrush::SetCenterPoint com pthGrBrush.SetCenterPoint(Point(145, 35)), você obterá o seguinte resultado.

Ilustração mostrando uma elipse que é preenchida de azul a aqua a partir de um ponto central que está fora da borda da elipse

Na ilustração anterior, os pontos na extremidade direita da elipse não são azul puro (embora estejam muito próximos disso). As cores no gradiente são posicionadas como se o preenchimento tivesse sido permitido chegar ao ponto (145, 35), a cor teria atingido azul puro (0, 0, 255). Mas o preenchimento nunca atinge (145, 35), pois um pincel de gradiente de caminho pinta apenas dentro de seu caminho.

Como a cor do gradiente de trajeto é calculada

Para cada pixel dentro do caminho, o pincel projeta um raio imaginário a partir do ponto central, passando pelo pixel, até onde o raio intersecta a borda do caminho. A cor nesse pixel é então interpolada linearmente entre a cor central e a cor do limite, com base na posição do pixel ao longo desse raio. Especificamente, o fator de interpolação é a proporção da distância do ponto central para o pixel, dividida pela distância total do ponto central até a interseção de limite.

Quando o ponto central está fora do caminho, pixels na lateral do caminho mais próximo ao ponto central têm raios curtos (porque o limite está próximo nessa direção). Como esses pixels estão relativamente distantes ao longo de seus raios curtos, eles aparecem mais próximos da cor central. Os pixels no lado mais distante do caminho têm raios longos e parecem mais próximos da cor da borda. Isso explica por que, na ilustração anterior, o limite próximo ao ponto central externo exibe uma cor próxima ao azul (a cor central) em vez de aqua (a cor do limite).