SkiaSharp(Portable Library)是一个Skia的绑定库,提供Xamarin中2D图型绘制功能。熟练掌握SkiaSharp的使用可以更好的自定义控件,如Microcharts。SkiaSharp引用很简单,通过Nuget搜索SkiaSharp.Views.Forms添加Package及SkiaSharp

同时要为平台项目(platform-specific projects)添加SkiaSharp.Views.FormsSkiaSharp.ViewsSkiaSharp

基础绘制功能

本文涉及的内容类似Android中的绘制部分,有兴趣的可以看看http://hencoder.com。

讲的真的很好!讲的真的很好!讲的真的很好!

SkiaSharp绘制图型主要涉及到的两个类SKCanvasViewSKPaint,SKCanvasView实例在处理PaintSurface事件时,根据SKPaint提供的一些绘制属性进行绘制,如颜色等。PaintSurface会多次触发,如横竖屏切换导致重绘。SKCanvasView还提供了InvalidateSurface方法可以让我们主动对视图进行重绘。

SKCanvasView的两种定义方式:
C#代码:

1
2
SKCanvasView canvasView = new SKCanvasView();
canvasView.PaintSurface += OnCanvasViewPaintSurface;

XAML代码:

1
2
3
4
5
xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
...
<skia:SKCanvasView PaintSurface="OnCanvasViewPaintSurface"/>

一个典型的PaintSurface事件处理方法:

1
2
3
4
5
6
7
8
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
}

SKPaintSurfaceEventArgs包含两个两个重要属性,分别是SKImageInfo类型的Info和SKSurface类型的Surface。Info中包含绘图Surface的一些信息,如宽高等。而Surface表示当前当前绘图缓冲区本身。SKSurface包含一个SKCanvas类型的Canvas属性,最终图型的绘制、变换和裁切等都是通过Canvas完成的.Clear方法作用则是将画布设置成透明色。

开始绘制之前当然是定义一个用来绘制的画笔SKPaint,绘制的通用属性通过SKPaint设定,如画笔的颜色、类型等。

1
2
3
4
5
6
var paint = new SKPaint
{
Style = SKPaintStyle.Stroke,
Color = Color.Red.ToSKColor(),
StrokeWidth = 10
};

Style表示花笔模式有三种: Fill, StrokeStrokeAndFill 。Fill是填充模式,Stroke 是画线模式(即勾边模式),StrokeAndFill是两种模式一并使用:既画线又填充。它的默认值是Fill填充模式。

Color属性设置画笔的颜色,通过SkiaSharp.Views.Forms命名空间下的ToSKColor的方法将Xamarin.Forms的Color转换为SkiaSharp中的SKColor

StrokeWidth则表示画笔的宽度。IsAntialias表示是否开启锯齿。

画圆 canvas.DrawCircle(cx:,cy:,radius:,paint:)

四个参数分别表示圆点的坐标和半径已经我们提前定义好的画笔,坐标系的原点是 View 左上角的那个点;水平方向是 x 轴,右正左负;竖直方向是 y 轴,下正上负。

1
canvas.DrawCircle(info.Width / 2, info.Height / 2, 100, paint);

画矩形 canvas.DrawRect(rect:,paint:)

rect是一个SKRect类型,SKRect构造函数中的left, top, right, bottom 是矩形四条边的坐标。

1
canvas.DrawRect(new SKRect(200, 200, 500, 500), paint);

画点 canvas.DrawPoint(x:,y:,paint:)

通过设置Paint的StrokeWidth属性来设置画的点的大小。通过Paint的StrokeCap属性设置点的形状,SKStrokeCap.Square画方点、SKStrokeCap.Round画圆点。

1
canvas.DrawPoint(info.Width / 2, info.Height / 2, paint);

批量画点 canvas.DrawPoints(mode:,points:,paint:)

其中model是一个SKPointMode枚举,包括Lines,PointsPolygon,Points表示绘制点,Lines则是绘制多个线段(每两个点连成一个线段),Polygon是将所有个点绘制成一条连线。

1
canvas.DrawPoints(SKPointMode.Points, new SKPoint[] { new SKPoint(100, 400), new SKPoint(200, 400), new SKPoint(200, 600), new SKPoint(300, 600) }, paint);

画椭圆 canvas.DrawOval(rect:,paint:)

参数同DrawRect

1
canvas.DrawOval(new SKRect(100, 200, 500, 400), paint)

画线 canvas.DrawLine(x0:,y0:,x1:,y1:,paint)

x0,y0,x1,y1分别是线的起点和终点坐标。通过Paint的StrokeCap属性设置决定线段两个端点的样式,SKStrokeCap.Square圆角、SKStrokeCap.Round直角(只有线段有一定宽度时才有明显效果)。

1
canvas.DrawLine(200, 200, 600, 500, paint);

画圆角矩形 canvas.DrawRoundRect(rect:,rx:,ry:,paint:)

rect表示矩形区域,rx 和 ry 是圆角的横向半径和纵向半径。

1
canvas.DrawRoundRect(new SKRect(200, 200, 500, 500), 50, 50, paint);

自定义图形绘制

绘制文本 canvas.DrawText(text:,x:,y:,paint:)

text表示要绘制的文本。x、y表示文本绘制起点在View中的坐标,默认为左下。

1
canvas.DrawText(str, 20, 200, paint);

SKPaint中可以进行更多文字显示相关的设置,如TextSkewX设置文本水平倾斜度,TextAlign是一个SKTextAlign枚举,设置文本的绘制方式默认为Left即从左到右绘制,Center表示文本从中间向两侧绘制,即从指定的x,y向左右两边绘制,Right表示右侧开始绘制。TextSize设置字体大小。

SKPaint还提供了一个MeasureText方法帮助我们获取当前显示文本的一下信息,该方法有多个重载方法:

paint.MeasureText(text:)

获取绘制文本的宽度

paint.MeasureText(text:,ref bounds:)

获取绘制文本的区域,通过ref参数bounds返回。

绘制图片 canvas.DrawBitmap(bitmap:,x:,y:,paint:)

bitmap是一个SKBitmap类型。x,y表示图片坐上绘制的位置。paint默认值为空,实际使用时可以忽略该参数。

我们该如何获得这个SKBitmap对象?SKBitmap提供了Decode方法,可以根据我们传入的数据流(SKManagedStream或Stream)解码生成一个SKBitmap对象。Decode包含多个重载方法。

1
2
3
4
...
var bitmap = SKBitmap.Decode(stream);
...
canvas.DrawBitmap(bitmap, 0, 0, null);

Xamarin.Forms中更多图片相关资料请跳转到这里

绘制路径canvas.DrawPath(path:,paint:)

SkiaSharp中绘制路径通过SKPath完成。SKPath定义了几组方法:

XXXTo

  • MoveTo 通常用来声明一条路径的起始点
  • LineTo 当前点到指定点绘制一条直线
  • ArcTo 根据当前点位置和指定的两个点绘制一条指定半径的曲线
  • CubicTo 绘制三次贝塞尔曲线
  • QuadTo 绘制二次贝塞尔曲线
  • ConicTo 不懂!add a rational quadratic Bezier spline, which can accurately render conic sections (ellipses, parabolas, and hyperbolas)

简单的示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
SKPath path = new SKPath();
// Define the first contour
path.MoveTo(0.5f * info.Width, 0.1f * info.Height);
path.LineTo(0.2f * info.Width, 0.4f * info.Height);
path.LineTo(0.8f * info.Width, 0.4f * info.Height);
// Define the second contour
path.MoveTo(0.5f * info.Width, 0.6f * info.Height);
path.LineTo(0.2f * info.Width, 0.9f * info.Height);
path.LineTo(0.8f * info.Width, 0.9f * info.Height);
path.Close();
SKPaint strokePaint = new SKPaint
{
Style = SKPaintStyle.Stroke,
Color = SKColors.Magenta,
StrokeWidth = 10
};
canvas.DrawPath(path, strokePaint);

调用Close方法使Path中已有内容形成一个封闭轮廓。

需要说明的是ArcTo方法的使用,看效果图理解参数吧:

1
2
path.MoveTo(0.5f * info.Width, 0.1f * info.Height);
path.ArcTo(0.2f * info.Width, 0.4f * info.Height, 0.8f * info.Width, 0.4f * info.Height, 200);

进行多条线绘制涉及到一个连接点即拐角样式的问题,SKPaint提供了StrokeJoin属性设置拐角样式,StrokeJoin是一个SKStrokeJoin类型枚举,有MiterRoundBevel三个值,分别表示直角、圆角和棱角三种样式。

RXXXTo

SKPath还定义了一组R开头的XXXTo方法,R表示的意思是relative。XXXTo方法中所有的点都是以(0,0)为源点,RXXXTo方法中所有的点都是以当前点为源点。

AddXXX

  • AddRect
  • AddRoundedRect
  • AddCircle
  • AddOval
  • AddArc
  • AddPath
  • AddPathReverse

AddXXX方法的作用是将整个图形或路径添加到当前路径的绘制。

最后更新: 2017年11月17日 22:36

原始链接: http://xamarin.xyz/2017/11/15/Xamarin.Forms 2D绘制基础(一)/