Condividi tramite


Pittura di dito in SkiaSharp

Usa le dita per dipingere sull'area di disegno.

Un SKPath oggetto può essere aggiornato e visualizzato continuamente. Questa funzionalità consente di utilizzare un percorso per il disegno interattivo, ad esempio in un programma di disegno con dita.

Esercizio nella pittura del dito

Il supporto tocco in Xamarin.Forms non consente di tenere traccia delle singole dita sullo schermo, quindi è stato sviluppato un Xamarin.Forms effetto di tracciamento del tocco per fornire ulteriore supporto tocco. Questo effetto è descritto nell'articolo Richiamo di eventi da Effetti. Il programma di esempio include due pagine che usano SkiaSharp, incluso un programma di dito.

La soluzione di esempio include questo evento di rilevamento tocco. Il progetto di libreria .NET Standard include la TouchEffect classe , l'enumerazione TouchActionType , il TouchActionEventHandler delegato e la TouchActionEventArgs classe . Ogni progetto di piattaforma include una TouchEffect classe per tale piattaforma. Il progetto iOS contiene anche una TouchRecognizer classe.

La pagina Finger Paint in SkiaSharpFormsDemos è un'implementazione semplificata della pittura delle dita. Non consente di selezionare il colore o la larghezza del tratto, non ha modo di cancellare l'area di disegno e naturalmente non è possibile salvare le opere d'arte.

Il file FingerPaintPage.xaml inserisce in SKCanvasView una singola cella Grid e associa a TouchEffect tale Gridoggetto :

<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 Il collegamento diretto a SKCanvasView non funziona in tutte le piattaforme.

Il file code-behind FingerPaintPage.xaml.cs definisce due raccolte per l'archiviazione degli oggetti, nonché un SKPaint oggetto per il SKPath rendering di questi percorsi:

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

Come suggerisce il nome, il inProgressPaths dizionario archivia i percorsi attualmente disegnati da una o più dita. La chiave del dizionario è l'ID tocco che accompagna gli eventi di tocco. Il completedPaths campo è una raccolta di percorsi che sono stati completati quando un dito che disegnava il percorso sollevato dallo schermo.

Il TouchAction gestore gestisce queste due raccolte. Quando un dito tocca per la prima volta lo schermo, viene aggiunto un nuovo SKPath oggetto a inProgressPaths. Man mano che il dito si muove, vengono aggiunti punti aggiuntivi al percorso. Quando il dito viene rilasciato, il percorso viene trasferito alla completedPaths raccolta. È possibile dipingere con più dita contemporaneamente. Dopo ogni modifica a uno dei percorsi o delle raccolte, l'oggetto SKCanvasView viene invalidato:

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

I punti che accompagnano gli eventi di rilevamento del tocco sono Xamarin.Forms coordinate, che devono essere convertite in coordinate SkiaSharp, ovvero pixel. Questo è lo scopo del ConvertToPixel metodo .

Il gestore esegue quindi semplicemente il PaintSurface rendering di entrambe le raccolte di percorsi. I percorsi completati precedenti vengono visualizzati sotto i percorsi in corso:

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

I tuoi dita sono limitati solo dal tuo talento:

Screenshot triplo della pagina Finger Paint

Si è visto come disegnare linee e definire le curve usando equazioni parametriche. Una sezione successiva su SkiaSharp Curves and Paths illustra i vari tipi di curve supportate SKPath . Ma un prerequisito utile è un'esplorazione delle trasformazioni SkiaSharp.