Compartir a través de


Dibujar objetos gráficos

Browse sample.Examina la muestra

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):

Screenshot of a red line.

Nota:

También hay una sobrecarga DrawLine que toma dos argumentos PointF.

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):

Screenshot of a dashed red line.

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):

Screenshot of a red ellipse.

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):

Screenshot of a red circle.

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):

Screenshot of a red filled ellipse.

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):

Screenshot of a dark blue rectangle.

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):

Screenshot of a dark blue square.

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):

Screenshot of a dark blue filled rectangle.

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):

Screenshot of a green rounded rectangle.

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):

Screenshot of a green filled rounded rectangle.

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:

Screenshot of a teal arc.

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:

Screenshot of a filled teal arc.

La propiedad FillColor del objeto ICanvas debe establecerse en Color antes de invocar al método FillArc.

Nota:

Hay sobrecargas DrawArc y FillArc que toman argumentos Rect y RectF.

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:

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:

Screenshot of a closed green triangle.

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:

Screenshot of a filled slate blue triangle.

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):

Screenshot of an image.

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:

Screenshot of strings using different alignment options.

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:

Screenshot of correctly rendered markdown.

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:

Screenshot of a circle drawn with fill and stroke.

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 tipo float, 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:

Screenshot of a objects drawn with shadows.

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:

Screenshot of a regular dashed square.

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:

Screenshot of an irregular dashed square.

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:

Screenshot of three lines with different line caps.

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:

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

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:

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

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:

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