Finger Painting in SkiaSharp

Télécharger l’exemple Télécharger l’exemple

Utilisez vos doigts pour peindre sur le canevas.

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

Un exercice de peinture aux doigts

La prise en charge tactile dans ne permet pas de suivre des doigts individuels sur l’écran. Un effet de suivi tactile a donc Xamarin.Forms été développé pour fournir une prise en Xamarin.Forms charge tactile supplémentaire. Cet effet est décrit dans l’article Appel d’événements à partir d’effets. L’exemple de programme Touch-Tracking Effect Demos comprend deux pages qui utilisent SkiaSharp, y compris un programme de peinture sur les doigts.

La solution SkiaSharpFormsDemos 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 au doigt. Il ne permet pas de sélectionner la couleur ou la largeur du trait, il n’a aucun moyen d’effacer le canevas et, bien sûr, vous ne pouvez pas enregistrer votre illustration.

Le fichier FingerPaintPage.xaml place le SKCanvasView dans une cellule Grid unique et joint à TouchEffect ce :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 direct au TouchEffectSKCanvasView ne fonctionne pas sous toutes les plateformes.

Le fichier code-behind FingerPaintPage.xaml.cs définit deux collections pour stocker les 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 son nom l’indique, le inProgressPaths dictionnaire stocke les chemins qui sont actuellement tracé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 a été levé de l’écran.

Le TouchAction gestionnaire gère ces deux collections. Lorsqu’un doigt touche l’écran pour la première fois, un nouveau SKPath est ajouté à inProgressPaths. À mesure que ce doigt se déplace, des points supplémentaires sont ajoutés au chemin. Lorsque le doigt est relâché, 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 ou collections, est SKCanvasView invalidé :

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. Les chemins terminés précédemment s’affichent 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 au doigt ne sont limitées que par votre talent :

Capture d’écran triple 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 pris SKPath en charge. Mais une condition préalable utile est l’exploration des transformations SkiaSharp.