绘制图形对象

浏览示例。 浏览示例

定义在 Microsoft.Maui.Graphics 命名空间中的 .NET 多平台应用 UI(.NET MAUI)图形使您能够在被定义为 ICanvas 对象的画布上绘制图形对象。

.NET MAUI GraphicsView 控件提供对对象的 ICanvas 访问,可以在该对象上设置属性并调用方法来绘制图形对象。 有关该 GraphicsView命令的详细信息,请参阅 GraphicsView。

注释

许多图形对象具有 Draw 和 Fill 方法,例如 DrawRectangle 和 FillRectangle。 使用 Draw 方法绘制的是形状的轮廓,而轮廓部分并未填充。 方法 Fill 绘制形状的轮廓,并填充形状。

图形对象使用在每个平台上识别的设备无关单位在ICanvas上绘制。 这可确保图形对象适当地缩放到基础平台的像素密度。

绘制线条

可以使用该方法绘制线条,该方法需要四ICanvas个DrawLinefloat参数来表示线条的起点和终点。

以下示例演示如何绘制线条:

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

在此示例中,红色对角线从 (10,10) 绘制到 (90,100):

红线的屏幕截图。

注释

还有一个重载,它采用了两个DrawLinePointF参数。

以下示例演示如何绘制虚线:

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

在此示例中,从 (10,10) 到 (90,100) 绘制红色虚线对角线:

红色虚线的屏幕截图。

有关虚线的详细信息,请参阅 绘制虚线对象。

绘制椭圆

可以在ICanvas上使用DrawEllipse方法绘制椭圆和圆,该方法需要x、y、width和height参数,参数类型为float。

以下示例演示如何绘制椭圆:

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

在此示例中,绘制尺寸为 100x50 的红色椭圆(10,10):

红色椭圆的屏幕截图。

若要绘制圆圈,请使 width 和 height 参数在 DrawEllipse 方法中相等:

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

在此示例中,绘制尺寸为 100x100 的红色圆圈(10,10):

红色圆圈的屏幕截图。

注释

也可以使用该方法绘制 DrawCircle 圆圈。

有关绘制虚线椭圆的信息,请参阅 “绘制虚线对象”。

可以使用FillEllipse方法绘制填充的椭圆,该方法还需要类型为x的y、width、height和float参数。

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

在此示例中,绘制尺寸为 150x50 的红色填充椭圆(10,10):

红色填充椭圆的屏幕截图。

在调用FillEllipse方法之前,必须将ICanvas对象的FillColor属性设置为Color。

也可以使用FillCircle方法绘制填充圆圈。

注释

有DrawEllipse和FillEllipse的重载,接收Rect和RectF自变量。 此外,还有 DrawCircle 和 FillCircle 的重载。

绘制矩形

使用DrawRectangle方法可以在ICanvas上绘制矩形和正方形,该方法需要x、y、width和height作为参数,且参数类型为float。

以下示例演示如何绘制矩形:

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

在此示例中,绘制尺寸为 100x50 的深蓝色矩形(10,10):

深蓝色矩形的屏幕截图。

若要绘制正方形,请将 width 和 height 参数设置为DrawRectangle方法中的相等值:

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

在此示例中,绘制尺寸为 100x100 的深蓝色正方形(10,10):

深蓝色正方形的屏幕截图。

有关绘制虚线矩形的信息,请参阅 “绘制虚线对象”。

使用FillRectangle方法可以绘制填充的矩形,该方法还需要float类型的x、y、width和height参数。

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

在此示例中,绘制尺寸为 100x50 的深蓝色填充矩形(10,10):

深蓝色填充矩形的屏幕截图。

在调用FillRectangle方法之前,必须将ICanvas对象的FillColor属性设置为Color。

注释

有DrawRectangle和FillRectangle的重载,它们采用Rect和RectF作为自变量。

绘制圆角矩形

可以在ICanvas上使用DrawRoundedRectangle方法绘制圆角矩形和正方形,该方法要求x、y、width、height和cornerRadius是float类型的参数。 cornerRadius 参数用于指定圆角矩形半径的值。

以下示例演示如何绘制圆角矩形:

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

在此示例中,绘制一个尺寸为100x50、圆角的绿色矩形,位置在坐标(10,10)。

绿色圆角矩形的屏幕截图。

有关绘制虚线圆角矩形的信息,请参阅 绘制虚线对象。

可以使用FillRoundedRectangle方法绘制填充的圆角矩形,该方法要求的参数有 x、y、width、height、cornerRadius 和float,这些参数的类型为float。

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

在此示例中,在 (10,10) 位置绘制一个圆角、尺寸为 100x50 的绿色填充矩形。

绿色填充圆角矩形的屏幕截图。

在调用FillRoundedRectangle方法之前,必须将ICanvas对象的FillColor属性设置为Color。

注释

存在 DrawRoundedRectangle 和 FillRoundedRectangle 重载采用 Rect 和 RectF 参数,并且重载允许为每个角单独指定其半径。

绘制弧线

可以使用DrawArc方法在ICanvas上绘制弧线,该方法需要float类型的x、y、width、height、startAngle和endAngle参数,以及bool类型的clockwise和closed参数。 该 startAngle 参数指定从 x 轴到弧线起点的角度。该 endAngle 参数指定从 x 轴到弧线终点的角度。该 clockwise 参数指定绘制弧线的方向,参数 closed 指定弧线的终点是否连接到起点。

以下示例演示如何绘制弧线:

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

在此示例中,在位置 (10,10) 绘制了尺寸为 100x100 的青色圆弧。 弧从 0 度以顺时针方向绘制到 180 度,但未闭合。

青色圆弧的屏幕截图。

有关绘制虚线弧线的信息,请参阅 绘制虚线对象。

可以使用FillArc方法绘制一个填充弧线,该方法需要类型为float的x、y、width、height、startAngle、endAngle参数,以及类型为bool的clockwise参数。

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

在此示例中,在位置(10,10)绘制一个尺寸为 100x100 的填充青色圆弧。 该弧以从 0 度到 180 度的顺时针方向绘制,并自动关闭:

填充青色弧的屏幕截图。

在调用FillArc方法之前,必须将ICanvas对象的FillColor属性设置为Color。

注释

有DrawArc和FillArc的重载,它们采用Rect和RectF作为自变量。

绘制路径

路径是一个或多个 轮廓的集合。 每个轮廓都是 连接的 直线和曲线的集合。 轮廓没有相互连接,但它们在视觉上可能会重叠。 有时单个轮廓可以重叠自身。

路径用于绘制曲线和复杂形状,可以在ICanvas上使用DrawPath方法进行绘制,该方法需要PathF参数。

轮廓通常以对方法的调用 PathF.MoveTo 开始,可以将其表示为 PointF 值或单独 x 和 y 坐标。 该MoveTo 调用在轮廓的开头确立一个点和初始当前点。 然后,可以调用以下方法,通过从当前点到方法中指定点的直线或曲线来延续轮廓,该点随后成为新的当前点:

  • LineTo 若要向路径添加直线,则为 。
  • AddArc 添加弧线,即圆或椭圆周长上的一条线。
  • CurveTo 以添加立方贝塞尔样条。
  • QuadTo 添加二次贝塞尔样条。

这些方法都不包含描述线条或曲线所需的所有数据。 相反,每个方法都与方法调用紧接其前面建立的当前点一起使用。 例如,该方法 LineTo 根据当前点向轮廓添加直线。

轮廓以另一个调用结束,该调用 MoveTo开始新的轮廓或调用 Close,这将关闭轮廓。 该方法 Close 自动将直线从当前点追加到轮廓的第一个点,并将路径标记为已关闭。

该 PathF 类还定义其他方法和属性。 以下方法将整个轮廓添加到路径:

以下示例演示如何绘制路径:

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

在此示例中,绘制了一个封闭的绿色三角形:

绿色实心三角形的屏幕截图。

可以使用 FillPath 来绘制填充路径,这还需要一个参数 PathF。

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

在此示例中,绘有一个填满的石板蓝三角形:

填充的石板蓝色三角形的屏幕截图。

在调用FillPath方法之前,必须将ICanvas对象的FillColor属性设置为Color。

重要

该FillPath方法具有一个重载,可以指定一个WindingMode,用于设置所使用的填充算法。 有关详细信息,请参阅 “绕行模式”。

绘制图像

可以在ICanvas上使用DrawImage方法绘制图像,该方法需要一个IImage参数,以及x、y、width和height的float类型参数。

以下示例演示如何加载图像并将其绘制到画布:

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);
}

在此示例中,图像被从程序集中检索并作为流加载。 然后,它以实际大小绘制为 (10,10):

图像的屏幕截图。

重要

加载嵌入到程序集中的图像需要将图像的生成操作设置为 嵌入资源,而不是 MauiImage。

绘制字符串

可以通过DrawString的重载在ICanvas上绘制字符串。 可以通过设置 Font属性 FontColor和 FontSize 属性来定义每个字符串的外观。 可以通过水平和垂直对齐选项指定字符串对齐方式,这些选项在字符串的边界框中执行对齐。

注释

字符串的边界框是由x、y、width 和 height 参数定义的。

以下示例演示如何绘制字符串:

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

在此示例中,将显示具有不同外观和对齐选项的字符串:

使用不同对齐选项的字符串的屏幕截图。

注释

重载功能 DrawString 还允许指定截断和行距。

有关绘制阴影的信息,请参阅 “绘制阴影”。

绘制带属性的文本

可以在ICanvas上使用DrawText方法绘制特性化文本,该方法需要IAttributedText参数,以及x、y、width、height参数均为float类型。 特性化文本是一个字符串,其中包含其文本部分的相关属性,通常表示样式数据。

以下示例演示如何绘制特性化文本:

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

在此示例中,markdown 转换为属性化文本,并显示正确的样式:

正确呈现 Markdown 的屏幕截图。

重要

绘制带属性文本需要将 Microsoft.Maui.Graphics.Text.Markdig NuGet 包添加到项目中。

用填充和笔划绘制

要在画布上绘制具有填充和笔划的图形对象,可以先调用填充方法,然后调用绘图方法。 例如,若要绘制边框,请将 FillColor 和 StrokeColor 属性设置为颜色,然后调用 FillRectangle 方法后跟 DrawRectangle 方法。

以下示例绘制一个带有描边轮廓的填充圆,并用作路径:

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

在此示例中,PathF 对象的笔划颜色和填充颜色被指定。 先绘制填充圆,再绘制圆的轮廓线。

用填充和笔划绘制的圆圈的屏幕截图。

警告

在填充方法之前调用绘图方法将导致 z 顺序不正确。 填充将覆盖笔画,因此笔画不可见。

绘制阴影

在ICanvas对象SetShadow上绘制的图形对象可以使用该方法应用阴影,该方法采用下列参数:

  • offset类型 SizeF,指定阴影的偏移量,该偏移量表示创建阴影的光源的位置。
  • blur类型 float,表示要应用于阴影的模糊量。
  • color,其类型为Color,定义阴影的颜色。

以下示例演示如何向填充的对象添加阴影:

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

在这些示例中,其光源位于不同位置的阴影被添加到填充对象中,其模糊量相同:

用阴影绘制的对象屏幕截图。

绘制虚线对象

ICanvas 对象具有一个类型为 float[] 的 StrokeDashPattern 属性。 此属性是一个值数组 float ,指示绘制对象笔划时要使用的短划线和间隙的模式。 float数组中的每个元素指定短划线或间隙的长度。 数组中的第一项指定短划线的长度,而数组中的第二项指定间距的长度。 因此, float 具有偶数索引值的值指定短划线,而 float 具有奇数索引值的值则指定间隙。

以下示例演示如何使用常规短划线绘制虚线正方形:

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

在此示例中,绘制一个带有常规虚线笔划的正方形:

常规虚线正方形的屏幕截图。

以下示例演示如何使用不规则短划线绘制虚线正方形:

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

在此示例中,绘制了一个不规则虚线的正方形:

不规则虚线正方形的屏幕截图。

控制线结束

一条线有三个部分:起始帽、线条体和终端帽。 开始和结束帽描述线段的开始和结束。

ICanvas 对象具有一个 StrokeLineCap 属性,其类型 LineCap为描述行的开始和结尾。 LineCap 枚举定义以下成员:

  • Butt,表示一条拥有方形端点的线条,被绘制成精确地延伸到线条的确切端点。 这是 StrokeLineCap 属性的默认值。
  • Round,表示带圆角的线条。
  • Square,表示一条带有正方形的线条,绘制为超出端点的距离等于线条宽度的一半。

以下示例演示如何设置 StrokeLineCap 属性:

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

在此示例中,红线在行的开头和结尾处四舍五入:

三行的屏幕截图,其中包含不同的线条上限。

控制线联接

ICanvas 对象具有一个 StrokeLineJoin 类型 LineJoin属性,该属性指定在对象的顶点中使用的联接类型。 LineJoin 枚举定义以下成员:

  • Miter,表示产生尖锐角或剪裁角的角顶点。 这是 StrokeLineJoin 属性的默认值。
  • Round,表示在角落产生圆弧的圆角。
  • Bevel,表示产生斜角角落的倒角顶点。

注释

当StrokeLineJoin属性设置为Miter时,可以通过float来限制对象中线条连接的斜接长度。

以下示例演示如何设置 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);

在此示例中,蓝色 PathF 对象在顶点处具有圆角接合点:

三个不同的 LineJoin 枚举成员效果的屏幕截图。

剪切对象

在绘制到图形ICanvas之前,可以使用以下方法剪裁图形对象:

  • ClipPath 裁剪对象,使得只有 PathF 对象的区域内的部分可见。
  • ClipRectangle 剪辑对象,以便仅显示矩形区域内的区域。 矩形可以通过使用float参数,或者使用Rect或RectF参数来指定。
  • SubtractFromClip 剪辑对象,以便仅显示矩形区域之外的区域。 可以使用float参数,或Rect或RectF参数指定矩形。

以下示例演示如何使用 ClipPath 该方法剪辑图像:

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);
}

在此示例中,图像使用一个 PathF 对象进行剪裁,该对象定义了一个圆心为 (100,90) 且半径为 80 的圆。 结果是只有圆形中图像的一部分可见:

使用 ClipPath 方法剪裁的图像的屏幕截图。

重要

ClipPath 方法具有一个重载,允许指定 WindingMode,用于设置剪辑时使用的填充算法。 有关详细信息,请参阅 “绕行模式”。

以下示例演示如何使用 SubtractFromClip 该方法剪辑图像:

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);
}

在此示例中,由提供给 SubtractFromClip 该方法的参数指定的矩形定义的区域将从图像中剪裁。 结果是只有矩形外部的图像部分可见:

使用 SubtractFromClip 方法剪裁的图像的屏幕截图。