Dibujar objetos gráficos
Los gráficos de .NET Multi-platform App UI (.NET MAUI), en el espacio de nombres Microsoft.Maui.Graphics, permiten dibujar objetos gráficos en un lienzo que se define como un objeto ICanvas.
El control GraphicsView de .NET MAUI proporciona acceso a un objeto ICanvas, en el que se pueden establecer propiedades e invocar métodos para dibujar objetos gráficos. Para obtener más información sobre GraphicsView, consulta GraphicsView.
Nota:
Muchos de los objetos gráficos tienen métodos Draw
y Fill
, por ejemplo, DrawRectangle y FillRectangle. Un método Draw
dibuja el contorno de la forma, que no se rellena. Un método Fill
dibuja el contorno de la forma y también lo rellena.
Los objetos gráficos se dibujan en un ICanvas mediante una unidad independiente del dispositivo reconocida por cada plataforma. Esto garantiza que los objetos gráficos se escalan adecuadamente a la densidad de píxeles de la plataforma subyacente.
Dibujar una línea
Las líneas se pueden dibujar en un ICanvas mediante el método DrawLine, que requiere cuatro argumentos float
que representan los puntos inicial y final de la línea.
El siguiente ejemplo muestra cómo dibujar una línea:
canvas.StrokeColor = Colors.Red;
canvas.StrokeSize = 6;
canvas.DrawLine(10, 10, 90, 100);
En este ejemplo, se dibuja una línea diagonal roja de (10,10) a (90,100):
El ejemplo siguiente muestra cómo dibujar una línea discontinua:
canvas.StrokeColor = Colors.Red;
canvas.StrokeSize = 4;
canvas.StrokeDashPattern = new float[] { 2, 2 };
canvas.DrawLine(10, 10, 90, 100);
En este ejemplo, se dibuja una línea diagonal discontinua roja de (10,10) a (90,100):
Para obtener más información sobre las líneas discontinuas, consulta Dibujar objetos discontinuos.
Dibujar una elipse
Las elipses y los círculos se pueden dibujar en un ICanvas mediante el método DrawEllipse, que requiere argumentos x
, y
, width
y height
, de tipo float
.
El siguiente ejemplo muestra cómo dibujar una elipse:
canvas.StrokeColor = Colors.Red;
canvas.StrokeSize = 4;
canvas.DrawEllipse(10, 10, 100, 50);
En este ejemplo, se dibuja una elipse roja con dimensiones 100x50 en (10,10):
Para dibujar un círculo, haz que los argumentos width
y height
para el método DrawEllipse sean iguales:
canvas.StrokeColor = Colors.Red;
canvas.StrokeSize = 4;
canvas.DrawEllipse(10, 10, 100, 100);
En este ejemplo, se dibuja un círculo rojo con dimensiones 100x100 en (10,10):
Nota:
Los círculos también se pueden dibujar con el método DrawCircle.
Para obtener información sobre cómo dibujar una elipse discontinua, consulta Dibujar objetos discontinuos.
Se puede dibujar una elipse rellenada con el método FillEllipse, que también requiere argumentos x
, y
, width
y height
de tipo float
:
canvas.FillColor = Colors.Red;
canvas.FillEllipse(10, 10, 150, 50);
En este ejemplo, se dibuja una elipse rellenada de color rojo con dimensiones 150x50 en (10,10):
La propiedad FillColor del objeto ICanvas debe establecerse en Color antes de invocar al método FillEllipse.
Los círculos rellenos también se pueden dibujar con el método FillCircle.
Nota:
Hay sobrecargas DrawEllipse y FillEllipse que toman argumentos Rect y RectF. Además, también hay sobrecargas DrawCircle y FillCircle.
Dibujar un rectángulo
Los rectángulos y los cuadrados se pueden dibujar en un ICanvas mediante el método DrawRectangle, que requiere argumentos x
, y
, width
y height
, de tipo float
.
El siguiente ejemplo muestra cómo dibujar un rectángulo:
canvas.StrokeColor = Colors.DarkBlue;
canvas.StrokeSize = 4;
canvas.DrawRectangle(10, 10, 100, 50);
En este ejemplo, se dibuja un rectángulo azul oscuro con dimensiones 100x50 en (10,10):
Para dibujar un cuadrado, haz que los argumentos width
y height
para el método DrawRectangle sean iguales:
canvas.StrokeColor = Colors.DarkBlue;
canvas.StrokeSize = 4;
canvas.DrawRectangle(10, 10, 100, 100);
En este ejemplo, se dibuja un cuadrado azul oscuro con dimensiones de 100x100 en (10,10):
Para obtener información sobre cómo dibujar un rectángulo discontinuo, consulta Dibujar objetos discontinuos.
Un rectángulo relleno se puede dibujar con el método FillRectangle, que también requiere argumentos x
, y
, width
y height
, de tipo float
:
canvas.FillColor = Colors.DarkBlue;
canvas.FillRectangle(10, 10, 100, 50);
En este ejemplo, se dibuja un rectángulo relleno de color azul oscuro con dimensiones 100x50 en (10,10):
La propiedad FillColor del objeto ICanvas debe establecerse en Color antes de invocar al método FillRectangle.
Nota:
Hay sobrecargas DrawRectangle y FillRectangle que toman argumentos Rect y RectF.
Dibujar un rectángulo redondeado
Los rectángulos y los cuadrados redondeados se pueden dibujar en un ICanvas mediante el método DrawRoundedRectangle, que requiere argumentos x
, y
, width
, height
y cornerRadius
de tipo float
. El argumento cornerRadius
especifica el radio utilizado para redondear las esquinas del rectángulo.
El ejemplo siguiente muestra cómo dibujar un rectángulo redondeado:
canvas.StrokeColor = Colors.Green;
canvas.StrokeSize = 4;
canvas.DrawRoundedRectangle(10, 10, 100, 50, 12);
En este ejemplo, se dibuja un rectángulo verde con esquinas redondeadas y dimensiones 100x50 en (10,10):
Para obtener información sobre cómo dibujar un rectángulo redondeado discontinuo, consulta Dibujar objetos discontinuos.
Se puede dibujar un rectángulo redondeado relleno con el método FillRoundedRectangle, que también requiere argumentos x
, y
, width
, height
y cornerRadius
de tipo float
:
canvas.FillColor = Colors.Green;
canvas.FillRoundedRectangle(10, 10, 100, 50, 12);
En este ejemplo, se dibuja un rectángulo relleno verde con esquinas redondeadas y dimensiones de 100x50 en (10,10):
La propiedad FillColor del objeto ICanvas debe establecerse en Color antes de invocar al método FillRoundedRectangle.
Nota:
Hay sobrecargas DrawRoundedRectangle y FillRoundedRectangle que toman argumentos Rect y RectF, y sobrecargas que permiten especificar el radio de cada esquina por separado.
Dibujar un arco
Los arcos se pueden dibujar en un ICanvas mediante el método DrawArc, que requiere argumentos x
, y
, width
, height
, startAngle
y endAngle
de tipo float
, y argumentos clockwise
y closed
de tipo bool
. El argumento startAngle
especifica el ángulo del eje X al punto inicial del arco. El argumento endAngle
especifica el ángulo del eje X al punto final del arco. El argumento clockwise
especifica la dirección en la que se dibuja el arco y el argumento closed
especifica si el punto final del arco se conectará al punto inicial.
El siguiente ejemplo muestra cómo dibujar un arco:
canvas.StrokeColor = Colors.Teal;
canvas.StrokeSize = 4;
canvas.DrawArc(10, 10, 100, 100, 0, 180, true, false);
En este ejemplo, se dibuja un arco teal de dimensiones 100x100 en (10,10). El arco se dibuja en una dirección en sentido de las agujas del reloj de 0 grados a 180 grados y no está cerrado:
Para obtener información sobre cómo dibujar un arco discontinuo, consulta Dibujar objetos discontinuos.
Un arco relleno se puede dibujar con el método FillArc, que requiere argumentos x
, y
, width
, height
, startAngle
y endAngle
, argumentos de tipo float
, y un argumento clockwise
de tipo bool
:
canvas.FillColor = Colors.Teal;
canvas.FillArc(10, 10, 100, 100, 0, 180, true);
En este ejemplo, se dibuja un arco de teal relleno de dimensiones 100x100 en (10,10). El arco se dibuja en una dirección en sentido de las agujas del reloj de 0 grados a 180 grados y se cierra automáticamente:
La propiedad FillColor del objeto ICanvas debe establecerse en Color antes de invocar al método FillArc.
Dibujar un trazado
Un trazado es una colección de uno o varios contornos. Cada contorno es una colección de líneas rectas y curvas conectadas. Los contornos no están conectados entre sí, pero pueden superponerse visualmente. A veces, un solo contorno se puede superponer.
Las rutas de acceso se usan para dibujar curvas y formas complejas y se pueden dibujar en un ICanvas mediante el método DrawPath, que requiere un argumento PathF.
Generalmente, un contorno comienza con una llamada al método PathF.MoveTo, que puedes expresar como un valor PointF o como coordenadas x
y y
independientes. La llamada MoveTo establece un punto al principio del contorno y un punto actual inicial. A continuación, puedes llamar a los métodos siguientes para continuar el contorno con una línea o curva desde el punto actual hasta un punto especificado en el método, que luego se convierte en el nuevo punto actual:
- LineTo para agregar una línea recta al trazado.
- AddArc para agregar un arco, que es una línea en la circunferencia de un círculo o elipse.
- CurveTo para agregar una curva spline de Bézier cúbica.
- QuadTo para agregar una curva spline de Bézier cuadrática.
Ninguno de estos métodos contiene todos los datos necesarios para describir la línea o curva. En su lugar, cada método funciona con el punto actual establecido por la llamada al método inmediatamente anterior. Por ejemplo, el método LineTo agrega una línea recta al contorno en función del punto actual.
Un contorno finaliza con otra llamada a MoveTo, que comienza un nuevo contorno o una llamada a Close, que cierra el contorno. El método Close anexa automáticamente una línea recta desde el punto actual hasta el primer punto del contorno y marca el trazado como cerrado.
La clase PathF también define otros métodos y propiedades. Los métodos siguientes agregan contornos enteros al trazado:
- AppendEllipse anexa un contorno de elipse cerrado al trazado.
- AppendCircle anexa un contorno de círculo cerrado al trazado.
- AppendRectangle anexa un contorno de rectángulo cerrado al trazado.
- AppendRoundedRectangle anexa un rectángulo cerrado con esquinas redondeadas al trazado.
El siguiente ejemplo muestra cómo dibujar un trazado:
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);
En este ejemplo, se dibuja un triángulo verde cerrado:
Se puede dibujar un trazado relleno con FillPath, que también requiere un 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);
En este ejemplo, se dibuja un triángulo azul pizarra relleno:
La propiedad FillColor del objeto ICanvas debe establecerse en Color antes de invocar al método FillPath.
Importante
El método FillPath tiene una sobrecarga que permite especificar un WindingMode, que establece el algoritmo de relleno que se usa. Para más información, consulte los Modos de desvanado.
Dibujar una imagen
Las imágenes se pueden dibujar en un ICanvas mediante el método DrawImage, que requiere un argumento IImage, y argumentos x
, y
, width
y height
, de tipo float
.
El ejemplo siguiente muestra cómo cargar una imagen y dibujarla en el lienzo:
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);
}
En este ejemplo, se recupera una imagen del conjunto y se carga como una secuencia. Después, se dibuja a tamaño real a (10,10):
Importante
Cargar una imagen insertada en un ensamblado requiere que la imagen tenga su acción de compilación establecida en Recurso incrustado en lugar de MauiImage.
Dibujar una cadena
Las cadenas se pueden dibujar en un ICanvas mediante una de las sobrecargas DrawString. La apariencia de cada cadena se puede definir estableciendo las propiedades Font, FontColor y FontSize. La alineación de cadenas se puede especificar mediante opciones de alineación horizontal y vertical que realizan la alineación dentro del cuadro de límite de la cadena.
Nota:
El cuadro de límite de una cadena se define mediante sus argumentos x
, y
, width
y height
.
Los ejemplos siguientes muestran cómo dibujar cadenas:
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);
En este ejemplo, se muestran cadenas con diferentes opciones de apariencia y alineación:
Nota:
Las sobrecargas DrawString también permiten especificar el truncamiento y el interlineado.
Para obtener información sobre dibujar sombras, consulta Dibujar una sombra.
Dibujar texto con atributos
El texto con atributos se puede dibujar en un ICanvas mediante el método DrawText, que requiere un argumento IAttributedText, y argumentos x
, y
, width
y height
de tipo float
. El texto con atributos es una cadena con atributos asociados para partes de su texto, que normalmente representa datos de estilo.
El ejemplo siguiente muestra cómo dibujar texto con atributos:
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);
En este ejemplo, Markdown se convierte en texto con atributos y se muestra con el estilo correcto:
Importante
Dibujar texto con atributos requiere que hayas agregado el paquete NuGet Microsoft.Maui.Graphics.Text.Markdig
al proyecto.
Dibujar con relleno y trazo
Los objetos gráficos con relleno y trazo se pueden dibujar en el lienzo llamando a un método de dibujo después de un método de relleno. Por ejemplo, para dibujar un rectángulo con contorno, establece las propiedades FillColor y StrokeColor en colores y, después, llama al método FillRectangle seguido del método DrawRectangle.
En el ejemplo siguiente se dibuja un círculo lleno, con un contorno de trazo, como trazado:
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);
En este ejemplo, se especifican los colores de trazo y relleno de un objeto PathF. El círculo relleno se dibuja y, después, el trazo de contorno del círculo:
Advertencia
Llamar a un método de dibujo antes de un método de relleno producirá un orden Z incorrecto. El relleno se dibujará sobre el trazo y el trazo no será visible.
Dibujar una sombra
Se puede aplicar una sombra a los objetos gráficos dibujados en ICanvas mediante el método SetShadow, que toma los argumentos siguientes:
offset
, de tipo SizeF, especifica un desplazamiento para la sombra, que representa la posición de una fuente de luz que crea la sombra.blur
, de tipofloat
, representa la cantidad de desenfoque que se va a aplicar a la sombra.color
, de tipo Color, define el color de la sombra.
Los ejemplos siguientes muestran cómo agregar sombras a objetos rellenados:
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);
En estos ejemplos, las sombras cuyas fuentes de luz están en diferentes posiciones se agregan a los objetos rellenados, con cantidades idénticas de desenfoque:
Dibujar objetos discontinuos
Los objetos ICanvas tienen una propiedad StrokeDashPattern de tipo float[]
. Esta propiedad es una matriz de valores float
que indican el patrón de guiones y espacios que se van a usar al dibujar el trazo de un objeto. Cada float
de la matriz especifica la longitud de un guión o un espacio. El primer elemento de la matriz especifica la longitud de un guión, mientras que el segundo elemento de la matriz especifica la longitud de un espacio. Por lo tanto, los valores float
con un valor de índice par especifican guiones, mientras que los valores float
con un valor de índice impar especifican espacios.
En el ejemplo siguiente se muestra cómo dibujar un cuadrado discontinuo con un guión normal:
canvas.StrokeColor = Colors.Red;
canvas.StrokeSize = 4;
canvas.StrokeDashPattern = new float[] { 2, 2 };
canvas.DrawRectangle(10, 10, 90, 100);
En este ejemplo, se dibuja un cuadrado con un trazo discontinuo normal:
En el ejemplo siguiente se muestra cómo dibujar un cuadrado discontinuo con un guión irregular:
canvas.StrokeColor = Colors.Red;
canvas.StrokeSize = 4;
canvas.StrokeDashPattern = new float[] { 4, 4, 1, 4 };
canvas.DrawRectangle(10, 10, 90, 100);
En este ejemplo, se dibuja un cuadrado con un trazo discontinuo irregular:
Control de finales de línea
Una línea tiene tres partes: extremo inicial, cuerpo de línea y extremo final. Los extremos inicial y final describen el inicio y final de una línea.
Los objetos ICanvas tienen una propiedad StrokeLineCap, de tipo LineCap, que describe el inicio y el final de una línea. La enumeración LineCap define los miembros siguientes:
Butt
, que representa una línea con un extremo cuadrado, dibujada para extenderse hasta el punto final exacto de la línea. Se trata del valor predeterminado de la propiedad StrokeLineCap.Round
, que representa una línea con un extremo redondeado.Square
, que representa una línea con un extremo cuadrado, dibujada para extenderse más allá del punto final a una distancia igual a la mitad del ancho de línea.
En el ejemplo siguiente se muestra cómo establecer la propiedad StrokeLineCap:
canvas.StrokeSize = 10;
canvas.StrokeColor = Colors.Red;
canvas.StrokeLineCap = LineCap.Round;
canvas.DrawLine(10, 10, 110, 110);
En este ejemplo, la línea roja se redondea al principio y al final de la línea:
Control de combinaciones de línea
Los objetos ICanvas tienen una propiedad StrokeLineJoin, de tipo LineJoin, que especifica el tipo de unión que se usa en los vértices de un objeto. La enumeración LineJoin define los miembros siguientes:
Miter
, que representa vértices angulares que producen una esquina aguda o recortada. Se trata del valor predeterminado de la propiedad StrokeLineJoin.Round
, que representa vértices redondeados que producen un arco circular en la esquina.Bevel
, que representa vértices biselados que producen una esquina diagonal.
Nota:
Cuando la propiedad StrokeLineJoin se establece en Miter
, la propiedad MiterLimit
se puede establecer en float
para limitar la longitud del ángulo de las uniones de línea en el objeto.
En el ejemplo siguiente se muestra cómo establecer la propiedad 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);
En este ejemplo, el objeto PathF azul tiene uniones redondeadas en sus vértices:
Recortar objetos
Los objetos gráficos que se dibujan en ICanvas pueden recortarse antes de dibujarse, mediante los métodos siguientes:
- ClipPath recorta un objeto para que solo sea visible el área que se encuentra dentro de la región de un objeto PathF.
- ClipRectangle recorta un objeto para que solo sea visible el área que se encuentra dentro de la región de un rectángulo. El rectángulo se puede especificar mediante argumentos
float
o mediante un argumento Rect o RectF. - SubtractFromClip recorta un objeto para que solo sea visible el área que está fuera de la región de un rectángulo. El rectángulo se puede especificar mediante argumentos
float
o mediante un argumento Rect o RectF.
En el siguiente ejemplo se muestra cómo usar el método ClipPath para recortar una imagen.
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);
}
En este ejemplo, la imagen se recorta mediante un objeto PathF que define un círculo que está centrado en (100 90) con un radio de 80. El resultado es que solo es visible la parte de la imagen que está dentro del círculo:
Importante
El método ClipPath tiene una sobrecarga que permite especificar un objeto WindingMode, que establece el algoritmo de relleno que se usa al recortar. Para más información, consulte los Modos de desvanado.
En el siguiente ejemplo se muestra cómo usar el método SubtractFromClip para recortar una imagen.
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);
}
En este ejemplo, se recorta de la imagen el área definida por el rectángulo especificado por los argumentos proporcionados al método SubtractFromClip. El resultado es que solo son visibles las partes de la imagen que están fuera del rectángulo: