在 SkiaSharp 中 小畫家 手指
使用手指在畫布上繪製。
SKPath
物件可以持續更新和顯示。 這項功能可讓路徑用於互動式繪圖,例如在手指繪製程式中。
中的 Xamarin.Forms 觸控支援不允許追蹤螢幕上的個別手指,因此 Xamarin.Forms 已開發觸控追蹤效果以提供額外的觸控支援。 從效果叫用事件一文 會說明此效果。 此範例程式包含兩個使用SkiaSharp的頁面,包括手指繪製程式。
此範例解決方案包含此觸控追蹤事件。 .NET Standard 連結庫專案包含 TouchEffect
類別、 TouchActionType
列舉、 TouchActionEventHandler
委派和 TouchActionEventArgs
類別。 每個平台專案都包含 TouchEffect
該平台的類別;iOS 專案也包含類別 TouchRecognizer
。
SkiaSharpFormsDemos 中的 [手指 小畫家] 頁面是簡化的手指繪製實作。 它不允許選取色彩或筆劃寬度,它無法清除畫布,當然您無法儲存您的藝術品。
Finger 小畫家 Page.xaml 檔案會將 放在SKCanvasView
單一儲存格Grid
中,並將附加TouchEffect
至 :Grid
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
xmlns:tt="clr-namespace:TouchTracking"
x:Class="SkiaSharpFormsDemos.Paths.FingerPaintPage"
Title="Finger Paint">
<Grid BackgroundColor="White">
<skia:SKCanvasView x:Name="canvasView"
PaintSurface="OnCanvasViewPaintSurface" />
<Grid.Effects>
<tt:TouchEffect Capture="True"
TouchAction="OnTouchEffectAction" />
</Grid.Effects>
</Grid>
</ContentPage>
將 TouchEffect
直接附加至 SKCanvasView
無法在所有平台下運作。
Finger 小畫家 Page.xaml.cs 程式代碼後置檔案會定義兩個SKPaint
集合來儲存SKPath
物件,以及用來轉譯這些路徑的物件:
public partial class FingerPaintPage : ContentPage
{
Dictionary<long, SKPath> inProgressPaths = new Dictionary<long, SKPath>();
List<SKPath> completedPaths = new List<SKPath>();
SKPaint paint = new SKPaint
{
Style = SKPaintStyle.Stroke,
Color = SKColors.Blue,
StrokeWidth = 10,
StrokeCap = SKStrokeCap.Round,
StrokeJoin = SKStrokeJoin.Round
};
public FingerPaintPage()
{
InitializeComponent();
}
...
}
如名稱所示, inProgressPaths
字典會儲存目前由一或多個手指繪製的路徑。 字典索引鍵是觸控事件隨附的觸控標識碼。 欄位 completedPaths
是一組路徑集合,當繪製從螢幕抬起路徑的手指時完成。
處理程式 TouchAction
會管理這兩個集合。 當手指第一次觸碰螢幕時,會將新的 SKPath
新增至 inProgressPaths
。 當手指移動時,會將其他點新增至路徑。 當手指放開時,路徑會傳送至 completedPaths
集合。 您可以使用多個手指同時繪製。 每次變更其中一個路徑或集合之後,就會 SKCanvasView
失效:
public partial class FingerPaintPage : ContentPage
{
...
void OnTouchEffectAction(object sender, TouchActionEventArgs args)
{
switch (args.Type)
{
case TouchActionType.Pressed:
if (!inProgressPaths.ContainsKey(args.Id))
{
SKPath path = new SKPath();
path.MoveTo(ConvertToPixel(args.Location));
inProgressPaths.Add(args.Id, path);
canvasView.InvalidateSurface();
}
break;
case TouchActionType.Moved:
if (inProgressPaths.ContainsKey(args.Id))
{
SKPath path = inProgressPaths[args.Id];
path.LineTo(ConvertToPixel(args.Location));
canvasView.InvalidateSurface();
}
break;
case TouchActionType.Released:
if (inProgressPaths.ContainsKey(args.Id))
{
completedPaths.Add(inProgressPaths[args.Id]);
inProgressPaths.Remove(args.Id);
canvasView.InvalidateSurface();
}
break;
case TouchActionType.Cancelled:
if (inProgressPaths.ContainsKey(args.Id))
{
inProgressPaths.Remove(args.Id);
canvasView.InvalidateSurface();
}
break;
}
}
...
SKPoint ConvertToPixel(Point pt)
{
return new SKPoint((float)(canvasView.CanvasSize.Width * pt.X / canvasView.Width),
(float)(canvasView.CanvasSize.Height * pt.Y / canvasView.Height));
}
}
觸控追蹤事件隨附的點為 Xamarin.Forms 座標;這些點必須轉換成SkiaSharp座標,也就是圖元。 這是方法的目的 ConvertToPixel
。
然後處理程式 PaintSurface
只會轉譯這兩個路徑集合。 先前完成的路徑會出現在進行中的路徑底下:
public partial class FingerPaintPage : ContentPage
{
...
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKCanvas canvas = args.Surface.Canvas;
canvas.Clear();
foreach (SKPath path in completedPaths)
{
canvas.DrawPath(path, paint);
}
foreach (SKPath path in inProgressPaths.Values)
{
canvas.DrawPath(path, paint);
}
}
...
}
您的手指畫只受限於您的天才:
您現在已瞭解如何使用參數方程式繪製線條和定義曲線。 SkiaSharp 曲線和路徑的後續章節涵蓋支援的各種曲線SKPath
類型。 但有用的先決條件是探索 SkiaSharp 轉換。