在 SkiaSharp 中绘制简单圆圈

了解 SkiaSharp 绘图的基础知识,包括画布和油漆对象

本文介绍使用 SkiaSharp 在 Xamarin.Forms 中绘制图形的概念,包括创建 SKCanvasView 对象来托管图形、处理 PaintSurface 事件,以及使用 SKPaint 对象指定颜色和其他绘图属性。

示例程序包含本系列 SkiaSharp 文章的所有示例代码。 第一页的名称为 Simple Circle,其中调用页面类 SimpleCirclePage。 此代码演示如何在页面中心绘制一个圆圈,半径为 100 像素。 圆的轮廓为红色,圆的内部为蓝色。

红色轮廓的蓝色圆圈

SimpleCircle 页类派生自 ContentPage,并包含 SkiaSharp 命名空间的两个 using 指令:

using SkiaSharp;
using SkiaSharp.Views.Forms;

类的以下构造函数创建一个 SKCanvasView 对象,附加 PaintSurface 事件的处理程序,并将 SKCanvasView 对象设置为页面的内容:

public SimpleCirclePage()
{
    Title = "Simple Circle";

    SKCanvasView canvasView = new SKCanvasView();
    canvasView.PaintSurface += OnCanvasViewPaintSurface;
    Content = canvasView;
}

SKCanvasView 占据页面的整个内容区域。 也可以将 SKCanvasView 与其他 Xamarin.FormsView 衍生工具组合在一起,如其他示例所示。

PaintSurface 事件处理程序是执行所有绘图的位置。 在程序运行时,可以多次调用此方法,因此它应保留重新创建图形显示所需的所有信息:

void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
    ...
}

事件附带的 SKPaintSurfaceEventArgs 对象有两个属性:

SKImageInfo 结构包含有关绘图图面的信息,最重要的是其宽度和高度(以像素为单位)。 SKSurface 对象表示绘图图面本身。 在此程序中,绘图图面是视频显示,但在其他程序中,SKSurface 对象还可以表示使用 SkiaSharp 绘制的位图。

SKSurface 最重要的属性是 SKCanvas 类型的 Canvas。 此类是用于执行实际绘图的图形绘图上下文。 SKCanvas 对象封装图形状态,其中包括图形转换和剪辑。

下面是 PaintSurface 事件处理程序的典型开始:

void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
    SKImageInfo info = args.Info;
    SKSurface surface = args.Surface;
    SKCanvas canvas = surface.Canvas;

    canvas.Clear();
    ...
}

Clear 方法使用透明颜色清除画布。 重载允许你为画布指定背景色。

这里的目标是绘制一个充满蓝色的红色圆圈。 由于此特定图形图像包含两种不同的颜色,因此需要在两个步骤中完成该作业。 第一步是绘制圆的轮廓。 若要指定线条的颜色和其他特征,请创建并初始化 SKPaint 对象:

void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
    ...
    SKPaint paint = new SKPaint
    {
        Style = SKPaintStyle.Stroke,
        Color = Colors.Red.ToSKColor(),
        StrokeWidth = 25
    };
    ...
}

Style 属性表示你想描边一条线(在本例中为圆的轮廓),而不是填充内部。 SKPaintStyle 枚举的三个成员如下所示:

默认为 Fill。 使用第三个选项可以划线并用相同颜色填充内部。

Color 属性设置为类型为 SKColor 的值。 获取 SKColor 值的一种方法是使用扩展方法 ToSKColor 将 Xamarin.FormsColor 值转换为 SKColor 值。 SkiaSharp.Views.Forms 命名空间中的 Extensions 类包括其他方法,这些方法在 Xamarin.Forms 值和 SkiaSharp 值之间进行转换。

StrokeWidth 属性指示线条的粗细。 此处,它设置为 25 像素。

使用该 SKPaint 对象绘制圆圈:

void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
    ...
    canvas.DrawCircle(info.Width / 2, info.Height / 2, 100, paint);
    ...
}

相对于显示图面左上角指定坐标。 X 坐标向右增加,Y 坐标将向下增加。 在讨论图形时,通常使用数学表示法 (x, y) 来表示点。 点 (0, 0) 是显示图面的左上角,通常称为原点

DrawCircle 的前两个参数指示圆中心的 X 和 Y 坐标。 这些值分配给显示图面的宽度和高度的一半,以将圆的中心置于显示图面的中心。 第三个参数指定圆的半径,最后一个参数是 SKPaint 对象。

若要填充圆圈的内部,可以更改 SKPaint 对象的两个属性,然后再次调用 DrawCircle。 此代码还显示了从 SKColors 结构的许多字段之一获取 SKColor 值的替代方法:

void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
    ...
    paint.Style = SKPaintStyle.Fill;
    paint.Color = SKColors.Blue;
    canvas.DrawCircle(args.Info.Width / 2, args.Info.Height / 2, 100, paint);
}

这一次,DrawCircle 调用使用 SKPaint 对象的新属性填充圆圈。

下面是在 iOS 和 Android 上运行的程序:

“Simple Circle”页面的三重屏幕截图

自行运行程序时,可以侧转手机或模拟器,查看图形的重绘方式。 每次重新绘制图形时,都会再次调用 PaintSurface 事件处理程序。

还可以使用渐变或位图图块为图形对象着色。 “SkiaSharp 着色器”部分中将讨论这些选项。

SKPaint 对象不仅仅是图形绘图属性的集合。 这些对象是轻量级的。 可以像此程序一样重复使用 SKPaint 对象,也可以为绘图属性的各种组合创建多个 SKPaint 对象。 可以在 PaintSurface 事件处理程序之外创建和初始化这些对象,并且可以将它们另存为页面类中的字段。

注意

SKPaint 类定义一个 IsAntialias,以便在图形呈现中启用抗锯齿。 反锯齿通常会导致视觉上更平滑的边缘,因此你可能希望针对大部分 SKPaint 对象将此属性设置为 true。 为简单起见,此属性大多数示例页面中设置。

虽然圆轮廓的宽度被指定为圆的半径的 25 像素 — 或四分之 — 一,但它看起来更薄,但有一个充分的理由:线条宽度的一半被蓝色圆遮盖。 DrawCircle 方法的参数定义圆的抽象几何坐标。 蓝色内部的大小设置为最接近的像素,但 25 像素宽的轮廓将几何圆 — 的一半跨越在内部和外部的一半。

与 Xamarin.Forms 集成文章中的下一个示例直观地演示了这一点。