Desenhar objetos gráficos
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):
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):
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):
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):
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):
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):
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):
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):
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):
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):
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 float
e clockwise
argumentos 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:
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:
A propriedade FillColor do objeto ICanvas deve ser definida como Color antes de invocar o método FillArc.
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:
- AppendEllipse anexa um contorno de elipse fechada ao caminho.
- AppendCircle anexa um contorno de círculo fechado ao caminho.
- AppendRectangle anexa um contorno de retângulo fechado ao caminho.
- AppendRoundedRectangle anexa um retângulo fechado com cantos arredondados 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:
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:
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):
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:
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:
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:
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 tipofloat
, 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:
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:
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:
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:
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:
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:
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: