Partager via


Peinture des doigts dans SkiaSharp

Utilisez vos doigts pour peindre sur le canevas.

Un SKPath objet peut être mis à jour et affiché en permanence. Cette fonctionnalité permet d’utiliser un chemin d’accès pour le dessin interactif, par exemple dans un programme de peinture de doigts.

Un exercice dans la peinture de doigts

La prise en charge tactile dans Xamarin.Forms n’autorise pas le suivi des doigts individuels sur l’écran, de sorte qu’un Xamarin.Forms effet de suivi tactile a été développé pour fournir une prise en charge tactile supplémentaire. Cet effet est décrit dans l’article Appel d’événements à partir d’effets. L’exemple de programme comprend deux pages qui utilisent SkiaSharp, y compris un programme de peinture des doigts.

L’exemple de solution inclut cet événement de suivi tactile. Le projet de bibliothèque .NET Standard inclut la TouchEffect classe, l’énumération TouchActionType , le TouchActionEventHandler délégué et la TouchActionEventArgs classe. Chacun des projets de plateforme inclut une TouchEffect classe pour cette plateforme ; le projet iOS contient également une TouchRecognizer classe.

La page Finger Paint dans SkiaSharpFormsDemos est une implémentation simplifiée de la peinture de doigts. Il n’autorise pas la sélection de la couleur ou de la largeur de trait, il n’a aucun moyen de effacer la zone de dessin, et bien sûr, vous ne pouvez pas enregistrer votre illustration.

Le fichier FingerPaintPage.xaml place l’élément SKCanvasView dans une cellule Grid unique et l’attache TouchEffect à ceci 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>

L’attachement TouchEffect direct au fichier SKCanvasView ne fonctionne pas sous toutes les plateformes.

Le fichier code-behind FingerPaintPage.xaml.cs définit deux collections pour le stockage des SKPath objets, ainsi qu’un SKPaint objet pour le rendu de ces chemins :

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

Comme le suggère le nom, le inProgressPaths dictionnaire stocke les chemins qui sont actuellement dessinés par un ou plusieurs doigts. La clé de dictionnaire est l’ID tactile qui accompagne les événements tactiles. Le completedPaths champ est une collection de chemins qui ont été terminés lorsqu’un doigt qui dessinait le chemin levé à partir de l’écran.

Le TouchAction gestionnaire gère ces deux collections. Lorsqu’un doigt touche d’abord l’écran, un nouveau SKPath est ajouté à inProgressPaths. À mesure que ce doigt se déplace, des points supplémentaires sont ajoutés au chemin d’accès. Lorsque le doigt est libéré, le chemin d’accès est transféré à la completedPaths collection. Vous pouvez peindre avec plusieurs doigts simultanément. Après chaque modification apportée à l’un des chemins d’accès ou collections, elle SKCanvasView est invalidée :

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

Les points qui accompagnent les événements de suivi tactile sont Xamarin.Forms des coordonnées ; celles-ci doivent être converties en coordonnées SkiaSharp, qui sont des pixels. C’est l’objectif de la ConvertToPixel méthode.

Le PaintSurface gestionnaire affiche ensuite simplement les deux collections de chemins d’accès. Les chemins d’accès terminés précédemment apparaissent sous les chemins en cours :

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

Vos peintures par doigts ne sont limitées que par votre talent :

Triple capture d’écran de la page Finger Paint

Vous avez maintenant vu comment dessiner des lignes et définir des courbes à l’aide d’équations paramétriques. Une section ultérieure sur les courbes et chemins SkiaSharp couvre les différents types de courbes qui SKPath prennent en charge. Mais un prérequis utile est une exploration des transformations SkiaSharp.