共用方式為


在 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 轉換