Desenhar objetos gráficos

Browse sample. Procurar no exemplo

Os gráficos .NET Multi-platform App UI (.NET MAUI), no namespace Microsoft.Maui.Graphics, permitem desenhar objetos gráficos em uma tela definida como um objeto ICanvas.

O controle .NET MAUI GraphicsView fornece acesso a um objeto ICanvas, no qual propriedades podem ser definidas e métodos invocados para desenhar objetos gráficos. Para obter mais informações sobre o GraphicsView, veja GraphicsView.

Observação

Muitos dos objetos gráficos possuem métodos Draw e Fill, por exemplo DrawRectangle e FillRectangle. Um método Draw desenha o contorno da forma, que não está preenchida. Um método Fill desenha o contorno da forma e também a preenche.

Os objetos gráficos são desenhados em um ICanvas usando uma unidade independente de dispositivo que é reconhecida por cada plataforma. Isso garante que os objetos gráficos sejam dimensionados adequadamente à densidade de pixels da plataforma subjacente.

Desenhar uma linha

As linhas podem ser desenhadas em um ICanvas usando o método DrawLine, que requer quatro float argumentos que representam os pontos inicial e final da linha.

O exemplo a seguir mostra como desenhar uma linha:

canvas.StrokeColor = Colors.Red;
canvas.StrokeSize = 6;
canvas.DrawLine(10, 10, 90, 100);

Nesse exemplo, uma linha diagonal vermelha é desenhada de (10,10) a (90,100):

Screenshot of a red line.

Observação

Há também uma sobrecarga DrawLine que leva dois PointF argumentos.

O exemplo a seguir mostra como desenhar uma linha tracejada:

canvas.StrokeColor = Colors.Red;
canvas.StrokeSize = 4;
canvas.StrokeDashPattern = new float[] { 2, 2 };
canvas.DrawLine(10, 10, 90, 100);

Nesse exemplo, uma linha diagonal tracejada vermelha é desenhada de (10,10) a (90,100):

Screenshot of a dashed red line.

Para obter mais informações sobre linhas tracejadas, veja Desenhar objetos tracejados.

Desenhar uma elipse

Elipses e círculos podem ser desenhados em um ICanvas usando o método DrawEllipse, que requer argumentos x, y, width, e height, do tipo float.

O exemplo a seguir mostra como desenhar uma elipse:

canvas.StrokeColor = Colors.Red;
canvas.StrokeSize = 4;
canvas.DrawEllipse(10, 10, 100, 50);

Nesse exemplo, uma elipse vermelha com dimensões 100x50 é desenhada em (10,10):

Screenshot of a red ellipse.

Para desenhar um círculo, torne os argumentos width e height do método DrawEllipse iguais:

canvas.StrokeColor = Colors.Red;
canvas.StrokeSize = 4;
canvas.DrawEllipse(10, 10, 100, 100);

Nesse exemplo, um círculo vermelho com dimensões 100x100 é desenhado em (10,10):

Screenshot of a red circle.

Observação

Círculos também podem ser desenhados com o método DrawCircle.

Para obter informações sobre como desenhar uma elipse tracejada, veja Desenhar objetos tracejados.

Uma elipse preenchida pode ser desenhada com o método FillEllipse, que também requer argumentos x, y, width e height, do tipo float:

canvas.FillColor = Colors.Red;
canvas.FillEllipse(10, 10, 150, 50);

Nesse exemplo, uma elipse preenchida em vermelho com dimensões 150x50 é desenhada em (10,10):

Screenshot of a red filled ellipse.

A propriedade FillColor do objeto ICanvas deve ser definida como Color antes de invocar o método FillEllipse.

Círculos preenchidos também podem ser desenhados com o método FillCircle.

Observação

Existem sobrecargas DrawEllipse e FillEllipse que aceitam argumentos Rect e RectF. Além disso, também existem sobrecargas DrawCircle e FillCircle.

Desenhar um retângulo

Retângulos e quadrados podem ser desenhados em um ICanvas usando o método DrawRectangle, que requer argumentos x, y, width, e height do tipofloat.

O exemplo a seguir mostra como desenhar um retângulo:

canvas.StrokeColor = Colors.DarkBlue;
canvas.StrokeSize = 4;
canvas.DrawRectangle(10, 10, 100, 50);

Nesse exemplo, um retângulo azul escuro com dimensões 100x50 é desenhado em (10,10):

Screenshot of a dark blue rectangle.

Para desenhar um quadrado, torne os argumentos width e height do método DrawRectangle iguais:

canvas.StrokeColor = Colors.DarkBlue;
canvas.StrokeSize = 4;
canvas.DrawRectangle(10, 10, 100, 100);

Nesse exemplo, um quadrado azul escuro com dimensões 100x100 é desenhado em (10,10):

Screenshot of a dark blue square.

Para obter informações sobre como desenhar um retângulo tracejado, veja Desenhar objetos tracejados.

Um retângulo preenchido pode ser desenhado com o método FillRectangle, que também requer argumentos x, y, width, e height do tipo float:

canvas.FillColor = Colors.DarkBlue;
canvas.FillRectangle(10, 10, 100, 50);

Nesse exemplo, um retângulo preenchido em azul escuro com dimensões 100x50 é desenhado em (10,10):

Screenshot of a dark blue filled rectangle.

A propriedade FillColor do objeto ICanvas deve ser definida como Color antes de invocar o método FillRectangle.

Observação

Existem sobrecargas DrawRectangle e FillRectangle que aceitam argumentos Rect e RectF.

Desenhe um retângulo arredondado

Retângulos e quadrados arredondados podem ser desenhados em um ICanvas usando o método DrawRoundedRectangle, que requer argumentos x, y, width, height, e cornerRadius do tipo float. O argumento cornerRadius especifica o raio usado para arredondar os cantos do retângulo.

O exemplo a seguir mostra como desenhar um retângulo arredondado:

canvas.StrokeColor = Colors.Green;
canvas.StrokeSize = 4;
canvas.DrawRoundedRectangle(10, 10, 100, 50, 12);

Nesse exemplo, um retângulo verde com cantos arredondados e dimensões 100x50 é desenhado em (10,10):

Screenshot of a green rounded rectangle.

Para obter informações sobre como desenhar um retângulo arredondado tracejado, veja Desenhar objetos tracejados.

Um retângulo arredondado preenchido pode ser desenhado com o método FillRoundedRectangle, que também requer argumentos x, y, width, height, e cornerRadius, do tipo float:

canvas.FillColor = Colors.Green;
canvas.FillRoundedRectangle(10, 10, 100, 50, 12);

Nesse exemplo, um retângulo preenchido em verde com cantos arredondados e dimensões 100x50 é desenhado em (10,10):

Screenshot of a green filled rounded rectangle.

A propriedade FillColor do objeto ICanvas deve ser definida como a Color antes de invocar o método FillRoundedRectangle.

Observação

Existem sobrecargas DrawRoundedRectangle e FillRoundedRectangle que aceitam argumentos Rect e RectF sobrecargas que permitem que o raio de cada canto seja especificado separadamente.

Desenhe um arco

Arcos podem ser desenhados em um ICanvas usando o método DrawArc, que requer argumentos x, y, width, height, startAngle e endAngle do tipo floate clockwiseargumentos e closed do tipo bool. O argumento startAngle especifica o ângulo do eixo x até o ponto inicial do arco. O argumento endAngle especifica o ângulo do eixo x até o ponto final do arco. O argumento clockwise especifica a direção na qual o arco é desenhado e o argumento closed especifica se o ponto final do arco será conectado ao ponto inicial.

O exemplo a seguir mostra como desenhar um arco:

canvas.StrokeColor = Colors.Teal;
canvas.StrokeSize = 4;
canvas.DrawArc(10, 10, 100, 100, 0, 180, true, false);

Nesse exemplo, um arco verde-azulado de dimensões 100x100 é desenhado em (10,10). O arco é desenhado no sentido horário de 0 graus a 180 graus e não é fechado:

Screenshot of a teal arc.

Para obter informações sobre como desenhar um arco tracejado, veja Desenhar objetos tracejados.

Um arco preenchido pode ser desenhado com o método FillArc, que requer argumentos x, y, width, height, startAngle e endAngle do tipo float e um argumento clockwise do tipo bool:

canvas.FillColor = Colors.Teal;
canvas.FillArc(10, 10, 100, 100, 0, 180, true);

Nesse exemplo, um arco verde-azulado preenchido com dimensões 100x100 é desenhado em (10,10). O arco é desenhado no sentido horário de 0 graus a 180 graus e é fechado automaticamente:

Screenshot of a filled teal arc.

A propriedade FillColor do objeto ICanvas deve ser definida como Color antes de invocar o método FillArc.

Observação

Existem sobrecargas DrawArc e FillArc que aceitam argumentos Rect e RectF.

Desenhar um caminho

Um caminho é uma coleção de um ou mais contornos. Cada contorno é uma coleção de linhas retas e curvas conectadas. Os contornos não estão conectados entre si, mas podem se sobrepor visualmente. Às vezes, um único contorno pode se sobrepor.

Caminhos são usados para desenhar curvas e formas complexas e podem ser desenhados em um ICanvas usando o método DrawPath, que requer um argumento PathF.

Um contorno geralmente começa com uma chamada ao método PathF.MoveTo, que você pode expressar como um valor PointF ou como coordenadas x e y separadas. A chamada MoveTo estabelece um ponto no início do contorno e um ponto atual inicial. Você pode então chamar os seguintes métodos para continuar o contorno com uma linha ou curva do ponto atual até um ponto especificado no método, que então se torna o novo ponto atual:

  • LineTo para adicionar uma linha reta ao caminho.
  • AddArc para adicionar um arco, que é uma linha na circunferência de um círculo ou elipse.
  • CurveTo para adicionar uma spline cúbica de Bezier.
  • QuadTo para adicionar um spline quadrático de Bézier.

Nenhum desses métodos contém todos os dados necessários para descrever a linha ou curva. Em vez disso, cada método funciona com o ponto atual estabelecido pela chamada do método imediatamente anterior. Por exemplo, o método LineTo adiciona uma linha reta ao contorno com base no ponto atual.

Um contorno termina com outra chamada para MoveTo, que inicia um novo contorno, ou uma chamada para Close, que fecha o contorno. O método Close anexa automaticamente uma linha reta do ponto atual ao primeiro ponto do contorno e marca o caminho como fechado.

A classe PathF também define outros métodos e propriedades. Os métodos a seguir adicionam contornos inteiros ao caminho:

O exemplo a seguir mostra como desenhar um caminho:

PathF path = new PathF();
path.MoveTo(40, 10);
path.LineTo(70, 80);
path.LineTo(10, 50);
path.Close();
canvas.StrokeColor = Colors.Green;
canvas.StrokeSize = 6;
canvas.DrawPath(path);

Nesse exemplo, um triângulo verde fechado é desenhado:

Screenshot of a closed green triangle.

Um caminho preenchido pode ser desenhado com FillPath, o que também requer um argumento PathF:

PathF path = new PathF();
path.MoveTo(40, 10);
path.LineTo(70, 80);
path.LineTo(10, 50);
canvas.FillColor = Colors.SlateBlue;
canvas.FillPath(path);

Nesse exemplo, um triângulo azul ardósia preenchido é desenhado:

Screenshot of a filled slate blue triangle.

A propriedade FillColor do objeto ICanvas deve ser definida como Color antes de invocar o método FillPath.

Importante

O método FillPath possui uma sobrecarga que permite que um WindingMode seja especificado, o que define o algoritmo de preenchimento usado. Para obter mais informações, veja Modos de enrolamento.

Desenhe uma imagem

As imagens podem ser desenhadas em um ICanvas usando o método DrawImage, que requer um argumento IImage e argumentos x, y, width, e height, do tipo float.

O exemplo a seguir mostra como carregar uma imagem e desenhá-la na tela:

using System.Reflection;
using IImage = Microsoft.Maui.Graphics.IImage;
using Microsoft.Maui.Graphics.Platform;

IImage image;
Assembly assembly = GetType().GetTypeInfo().Assembly;
using (Stream stream = assembly.GetManifestResourceStream("GraphicsViewDemos.Resources.Images.dotnet_bot.png"))
{
    image = PlatformImage.FromStream(stream);
}

if (image != null)
{
    canvas.DrawImage(image, 10, 10, image.Width, image.Height);
}

Nesse exemplo, uma imagem é recuperada do assembly e carregada como um fluxo. Em seguida, é desenhado em tamanho real em (10,10):

Screenshot of an image.

Importante

Carregar uma imagem incorporada em um assembly requer que a imagem tenha sua ação de construção definida como Embedded Resource em vez de MauiImage.

Desenhe uma corda

Strings podem ser desenhadas em um ICanvas usando uma das DrawString sobrecargas. A aparência de cada string pode ser definida definindo as propriedades Font, FontColor, e FontSize. O alinhamento da cadeia de caracteres pode ser especificado por opções de alinhamento horizontal e vertical que executam o alinhamento dentro da caixa delimitadora da cadeia de caracteres.

Observação

A caixa delimitadora de uma string é definida por seus argumentos x, y, width, e height.

Os exemplos a seguir mostram como desenhar strings:

canvas.FontColor = Colors.Blue;
canvas.FontSize = 18;

canvas.Font = Font.Default;
canvas.DrawString("Text is left aligned.", 20, 20, 380, 100, HorizontalAlignment.Left, VerticalAlignment.Top);
canvas.DrawString("Text is centered.", 20, 60, 380, 100, HorizontalAlignment.Center, VerticalAlignment.Top);
canvas.DrawString("Text is right aligned.", 20, 100, 380, 100, HorizontalAlignment.Right, VerticalAlignment.Top);

canvas.Font = Font.DefaultBold;
canvas.DrawString("This text is displayed using the bold system font.", 20, 140, 350, 100, HorizontalAlignment.Left, VerticalAlignment.Top);

canvas.Font = new Font("Arial");
canvas.FontColor = Colors.Black;
canvas.SetShadow(new SizeF(6, 6), 4, Colors.Gray);
canvas.DrawString("This text has a shadow.", 20, 200, 300, 100, HorizontalAlignment.Left, VerticalAlignment.Top);

Nesse exemplo, são exibidas strings com diferentes opções de aparência e alinhamento:

Screenshot of strings using different alignment options.

Observação

As DrawString overloads também permitem que o truncamento e o espaçamento entre linhas sejam especificados.

Para obter informações sobre como desenhar sombras, veja Desenhar uma sombra.

Desenhar texto atribuído

O texto atribuído pode ser desenhado em um ICanvas usando o método DrawText, que requer um argumento IAttributedText e argumentos x y, width, e height, do tipo float. Texto atribuído é uma string com atributos associados para partes de seu texto, que normalmente representa dados de estilo.

O exemplo a seguir mostra como desenhar texto atribuído:

using Microsoft.Maui.Graphics.Text;
...

canvas.Font = new Font("Arial");
canvas.FontSize = 18;
canvas.FontColor = Colors.Blue;

string markdownText = @"This is *italic text*, **bold text**, __underline text__, and ***bold italic text***.";
IAttributedText attributedText = MarkdownAttributedTextReader.Read(markdownText); // Requires the Microsoft.Maui.Graphics.Text.Markdig package
canvas.DrawText(attributedText, 10, 10, 400, 400);

Nesse exemplo, o markdown é convertido em texto atribuído e exibido com o estilo correto:

Screenshot of correctly rendered markdown.

Importante

O desenho do texto atribuído requer que você tenha adicionado o pacote Microsoft.Maui.Graphics.Text.Markdig NuGet ao seu projeto.

Desenhar com preenchimento e traço

Objetos gráficos com preenchimento e traçado podem ser desenhados na tela chamando um método desenho após um método de preenchimento. Por exemplo, para desenhar um retângulo contornado, defina as propriedades FillColor e StrokeColor como cores e chame o método FillRectangle seguido pelo método DrawRectangle.

O exemplo a seguir desenha um círculo preenchido, com um contorno traçado, como um caminho:

float radius = Math.Min(dirtyRect.Width, dirtyRect.Height) / 4;

PathF path = new PathF();
path.AppendCircle(dirtyRect.Center.X, dirtyRect.Center.Y, radius);

canvas.StrokeColor = Colors.Blue;
canvas.StrokeSize = 10;
canvas.FillColor = Colors.Red;

canvas.FillPath(path);
canvas.DrawPath(path);

Nesse exemplo, as cores de traço e preenchimento de um objeto PathF são especificadas. O círculo preenchido é desenhado e, em seguida, o contorno do círculo:

Screenshot of a circle drawn with fill and stroke.

Aviso

Chamar um método desenhar antes de um método preenchimento resultará em uma ordem z incorreta. O preenchimento será desenhado sobre o traço e o traço não ficará visível.

Desenhe uma sombra

Objetos gráficos desenhados em um ICanvas podem ter uma sombra aplicada usando o método SetShadow, que recebe os seguintes argumentos:

  • offset, do tipo SizeF, especifica um deslocamento para a sombra, que representa a posição de uma fonte de luz que cria a sombra.
  • blur, do tipo float, representa a quantidade de desfoque a ser aplicada à sombra.
  • color, do tipo Color, define a cor da sombra.

Os exemplos a seguir mostram como adicionar sombras a objetos preenchidos:

canvas.FillColor = Colors.Red;
canvas.SetShadow(new SizeF(10, 10), 4, Colors.Grey);
canvas.FillRectangle(10, 10, 90, 100);

canvas.FillColor = Colors.Green;
canvas.SetShadow(new SizeF(10, -10), 4, Colors.Grey);
canvas.FillEllipse(110, 10, 90, 100);

canvas.FillColor = Colors.Blue;
canvas.SetShadow(new SizeF(-10, 10), 4, Colors.Grey);
canvas.FillRoundedRectangle(210, 10, 90, 100, 25);

Nesses exemplos, sombras cujas fontes de luz estão em posições diferentes são adicionadas aos objetos preenchidos, com quantidades idênticas de desfoque:

Screenshot of a objects drawn with shadows.

Desenhar objetos tracejados

ICanvas objetos têm uma propriedade StrokeDashPattern, do tipo float[]. Essa propriedade é uma matriz de valores float que indicam o padrão de traços e espaços que devem ser usados ao desenhar o traço de um objeto. Cada float na matriz especifica o comprimento de um traço ou lacuna. O primeiro item da matriz especifica o comprimento de um traço, enquanto o segundo item da matriz especifica o comprimento de uma lacuna. Portanto, valores float com valor de índice par especificam traços, enquanto valores float com valor de índice ímpar especificam lacunas.

O exemplo a seguir mostra como desenhar um quadrado tracejado usando um traço regular:

canvas.StrokeColor = Colors.Red;
canvas.StrokeSize = 4;
canvas.StrokeDashPattern = new float[] { 2, 2 };
canvas.DrawRectangle(10, 10, 90, 100);

Nesse exemplo, um quadrado com um traço tracejado regular é desenhado:

Screenshot of a regular dashed square.

O exemplo a seguir mostra como desenhar um quadrado tracejado usando um traço irregular:

canvas.StrokeColor = Colors.Red;
canvas.StrokeSize = 4;
canvas.StrokeDashPattern = new float[] { 4, 4, 1, 4 };
canvas.DrawRectangle(10, 10, 90, 100);

Nesse exemplo, um quadrado com um traço tracejado irregular é desenhado:

Screenshot of an irregular dashed square.

A linha de controle termina

Uma linha tem três partes: limite inicial, corpo da linha e limite final. As letras iniciais e finais descrevem o início e o fim de uma linha.

ICanvas objetos possuem uma propriedade StrokeLineCap, do tipo LineCap, que descreve o início e o fim de uma linha. A enumeração LineCap define os seguintes membros:

  • Butt, que representa uma linha com uma extremidade quadrada, desenhada para se estender até o ponto final exato da linha. Este é o valor padrão da propriedade StrokeLineCap.
  • Round, que representa uma linha com extremidade arredondada.
  • Square, que representa uma linha com extremidade quadrada, desenhada para se estender além da extremidade até uma distância igual à metade da largura da linha.

O exemplo a seguir mostra como definir a propriedade StrokeLineCap:

canvas.StrokeSize = 10;
canvas.StrokeColor = Colors.Red;
canvas.StrokeLineCap = LineCap.Round;
canvas.DrawLine(10, 10, 110, 110);

Nesse exemplo, a linha vermelha é arredondada no início e no final da linha:

Screenshot of three lines with different line caps.

Junções de linha de controle

ICanvas objetos possuem uma propriedade StrokeLineJoin, do tipo LineJoin, que especifica o tipo de junção usada nos vértices de um objeto. A enumeração LineJoin define os seguintes membros:

  • Miter, que representa vértices angulares que produzem um canto agudo ou cortado. Este é o valor padrão da propriedade StrokeLineJoin.
  • Round, que representa vértices arredondados que produzem um arco circular no canto.
  • Bevel, que representa vértices chanfrados que produzem um canto diagonal.

Observação

Quando a propriedade StrokeLineJoin é definida como Miter, a propriedade MiterLimit pode ser definida como float para limitar o comprimento da esquadria das junções de linha no objeto.

O exemplo a seguir mostra como definir a propriedade StrokeLineJoin:

PathF path = new PathF();
path.MoveTo(10, 10);
path.LineTo(110, 50);
path.LineTo(10, 110);

canvas.StrokeSize = 20;
canvas.StrokeColor = Colors.Blue;
canvas.StrokeLineJoin = LineJoin.Round;
canvas.DrawPath(path);

Nesse exemplo, o objeto azul PathF possui junções arredondadas em seus vértices:

Screenshot of the effect of the three different LineJoin enumeration members.

Objetos clip

Objetos gráficos desenhados em um ICanvas podem ser recortados antes do desenho, com os seguintes métodos:

  • ClipPath recorta um objeto para que apenas a área que está dentro da região de um objeto PathF fique visível.
  • ClipRectangle recorta um objeto para que apenas a área que está dentro da região de um retângulo fique visível. O retângulo pode ser especificado usando argumentos float ou por um argumento Rect ou RectF.
  • SubtractFromClip recorta um objeto para que apenas a área que está fora da região de um retângulo fique visível. O retângulo pode ser especificado usando argumentos float ou por um argumento Rect ou RectF.

O exemplo a seguir mostra como usar o método ClipPath para recortar uma imagem:

using System.Reflection;
using IImage = Microsoft.Maui.Graphics.IImage;
using Microsoft.Maui.Graphics.Platform;

IImage image;
Assembly assembly = GetType().GetTypeInfo().Assembly;
using (Stream stream = assembly.GetManifestResourceStream("GraphicsViewDemos.Resources.Images.dotnet_bot.png"))
{
    image = PlatformImage.FromStream(stream);
}

if (image != null)
{
    PathF path = new PathF();
    path.AppendCircle(100, 90, 80);
    canvas.ClipPath(path);  // Must be called before DrawImage
    canvas.DrawImage(image, 10, 10, image.Width, image.Height);
}

Nesse exemplo, a imagem é recortada usando um objeto PathF que define um círculo centrado em (100,90) com raio de 80. O resultado é que apenas a parte da imagem dentro do círculo fica visível:

Screenshot of an image that's been clipped with the ClipPath method.

Importante

O método ClipPath tem uma sobrecarga que permite que um WindingMode seja especificado, o que define o algoritmo de preenchimento usado ao recortar. Para obter mais informações, veja Modos de enrolamento.

O exemplo a seguir mostra como usar o método SubtractFromClip para recortar uma imagem:

using System.Reflection;
using IImage = Microsoft.Maui.Graphics.IImage;
using Microsoft.Maui.Graphics.Platform;

IImage image;
Assembly assembly = GetType().GetTypeInfo().Assembly;
using (Stream stream = assembly.GetManifestResourceStream("GraphicsViewDemos.Resources.Images.dotnet_bot.png"))
{
    image = PlatformImage.FromStream(stream);
}

if (image != null)
{
    canvas.SubtractFromClip(60, 60, 90, 90);
    canvas.DrawImage(image, 10, 10, image.Width, image.Height);
}

Nesse exemplo, a área definida pelo retângulo especificado pelos argumentos fornecidos ao método SubtractFromClip é cortada da imagem. O resultado é que apenas as partes da imagem fora do retângulo ficam visíveis:

Screenshot of an image that's been clipped with the SubtractFromClip method.