Partager via


Points et tirets dans SkiaSharp

Maîtriser les intricités du dessin pointillés et des traits pointillés dans SkiaSharp

SkiaSharp vous permet de dessiner des lignes qui ne sont pas solides, mais sont plutôt composées de points et de tirets :

Trait en pointillé

Pour ce faire, vous utilisez un effet de chemin d’accès, qui est une instance de la SKPathEffect classe que vous avez définie sur la PathEffect propriété de SKPaint. Vous pouvez créer un effet de chemin (ou combiner des effets de chemin) à l’aide de l’une des méthodes de création statique définies par SKPathEffect. (SKPathEffect est l’un des six effets pris en charge par SkiaSharp ; les autres sont décrits dans la section Effet SkiaSharp.)

Pour dessiner des lignes pointillées ou en pointillés, vous utilisez la SKPathEffect.CreateDash méthode statique. Il existe deux arguments : il s’agit d’un tableau de float valeurs qui indiquent les longueurs des points et des tirets et la longueur des espaces entre eux. Ce tableau doit avoir un nombre pair d’éléments, et il doit y avoir au moins deux éléments. (Il peut y avoir zéro élément dans le tableau, mais cela entraîne une ligne solide.) S’il existe deux éléments, la première est la longueur d’un point ou d’un tiret, et la seconde est la longueur de l’écart avant le point ou le tiret suivant. S’il existe plus de deux éléments, ils se trouvent dans cet ordre : longueur de tiret, longueur d’écart, longueur de tiret, longueur d’écart, longueur d’écart, etc.

En règle générale, vous souhaiterez faire en sorte que le tiret et la longueur de l’écart soient multiples de la largeur du trait. Si la largeur du trait est de 10 pixels, par exemple, le tableau { 10, 10 } dessine une ligne en pointillés où les points et les écarts sont de la même longueur que l’épaisseur du trait.

Toutefois, le StrokeCap paramètre de l’objet SKPaint affecte également ces points et tirets. Comme vous le verrez bientôt, cela a un impact sur les éléments de ce tableau.

Les lignes pointillées et pointillées sont illustrées sur la page Points et Tirets . Le fichier DotsAndDashesPage.xaml instancie deux Picker vues, une pour vous permettre de sélectionner une limite de trait et la seconde pour sélectionner un tableau de tirets :

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:skia="clr-namespace:SkiaSharp;assembly=SkiaSharp"
             xmlns:skiaforms="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
             x:Class="SkiaSharpFormsDemos.Paths.DotsAndDashesPage"
             Title="Dots and Dashes">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <Picker x:Name="strokeCapPicker"
                Title="Stroke Cap"
                Grid.Row="0"
                Grid.Column="0"
                SelectedIndexChanged="OnPickerSelectedIndexChanged">
            <Picker.ItemsSource>
                <x:Array Type="{x:Type skia:SKStrokeCap}">
                    <x:Static Member="skia:SKStrokeCap.Butt" />
                    <x:Static Member="skia:SKStrokeCap.Round" />
                    <x:Static Member="skia:SKStrokeCap.Square" />
                </x:Array>
            </Picker.ItemsSource>
            <Picker.SelectedIndex>
                0
            </Picker.SelectedIndex>
        </Picker>

        <Picker x:Name="dashArrayPicker"
                Title="Dash Array"
                Grid.Row="0"
                Grid.Column="1"
                SelectedIndexChanged="OnPickerSelectedIndexChanged">
            <Picker.ItemsSource>
                <x:Array Type="{x:Type x:String}">
                    <x:String>10, 10</x:String>
                    <x:String>30, 10</x:String>
                    <x:String>10, 10, 30, 10</x:String>
                    <x:String>0, 20</x:String>
                    <x:String>20, 20</x:String>
                    <x:String>0, 20, 20, 20</x:String>
                </x:Array>
            </Picker.ItemsSource>
            <Picker.SelectedIndex>
                0
            </Picker.SelectedIndex>
        </Picker>

        <skiaforms:SKCanvasView x:Name="canvasView"
                                PaintSurface="OnCanvasViewPaintSurface"
                                Grid.Row="1"
                                Grid.Column="0"
                                Grid.ColumnSpan="2" />
    </Grid>
</ContentPage>

Les trois premiers éléments du dashArrayPicker principe que la largeur du trait est de 10 pixels. Le tableau { 10, 10 } est destiné à une ligne en pointillés, { 30, 10 } est destiné à une ligne en pointillés et { 10, 10, 30, 10 } est destiné à une ligne point-et-tiret. (Les trois autres seront abordés sous peu.)

Le DotsAndDashesPage fichier code-behind contient le PaintSurface gestionnaire d’événements et quelques routines d’assistance pour accéder aux Picker vues :

void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
    SKImageInfo info = args.Info;
    SKSurface surface = args.Surface;
    SKCanvas canvas = surface.Canvas;

    canvas.Clear();

    SKPaint paint = new SKPaint
    {
        Style = SKPaintStyle.Stroke,
        Color = SKColors.Blue,
        StrokeWidth = 10,
        StrokeCap = (SKStrokeCap)strokeCapPicker.SelectedItem,
        PathEffect = SKPathEffect.CreateDash(GetPickerArray(dashArrayPicker), 20)
    };

    SKPath path = new SKPath();
    path.MoveTo(0.2f * info.Width, 0.2f * info.Height);
    path.LineTo(0.8f * info.Width, 0.8f * info.Height);
    path.LineTo(0.2f * info.Width, 0.8f * info.Height);
    path.LineTo(0.8f * info.Width, 0.2f * info.Height);

    canvas.DrawPath(path, paint);
}

float[] GetPickerArray(Picker picker)
{
    if (picker.SelectedIndex == -1)
    {
        return new float[0];
    }

    string str = (string)picker.SelectedItem;
    string[] strs = str.Split(new char[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries);
    float[] array = new float[strs.Length];

    for (int i = 0; i < strs.Length; i++)
    {
        array[i] = Convert.ToSingle(strs[i]);
    }
    return array;
}

Dans les captures d’écran suivantes, l’écran iOS situé à l’extrême gauche montre une ligne en pointillés :

Capture d’écran triple de la page Points et Tirets

Toutefois, l’écran Android est également censé afficher une ligne en pointillé à l’aide du tableau { 10, 10 } mais au lieu de cela, la ligne est solide. Que s’est-il passé ? Le problème est que l’écran Android a également un paramètre de limite de traits de Square. Cela étend tous les tirets de la moitié de la largeur du trait, ce qui les oblige à combler les lacunes.

Pour contourner ce problème lors de l’utilisation d’une limite de SquareRoundtrait ou , vous devez réduire les longueurs de tirets dans le tableau par la longueur de trait (parfois résultant d’une longueur de tiret de 0) et augmenter les longueurs d’écart par la longueur du trait. Voici comment les trois tableaux de tirets finaux du Picker fichier XAML ont été calculés :

  • { 10, 10 } devient { 0, 20 } pour une ligne en pointillé
  • { 30, 10 } devient { 20, 20 } pour une ligne en pointillés
  • { 10, 10, 30, 10 } devient { 0, 20, 20, 20} pour une ligne pointillée et pointillée

L’écran UWP montre que la ligne pointillée et pointillée pour un capuchon de trait .Round Le Round capuchon de trait donne souvent la meilleure apparence des points et tirets en lignes épaisses.

Jusqu’à présent, aucune mention n’a été faite du deuxième paramètre à la SKPathEffect.CreateDash méthode. Ce paramètre est nommé phase et fait référence à un décalage dans le modèle point-and-dash pour le début de la ligne. Par exemple, si le tableau de tirets est { 10, 10 } et que la phase valeur est 10, la ligne commence par un écart plutôt qu’un point.

Une application intéressante du phase paramètre est dans une animation. La page Spirale animée est similaire à la page Spirale Archimedean, sauf que la AnimatedSpiralPage classe anime le phase paramètre à l’aide de la Xamarin.FormsDevice.Timer méthode :

public class AnimatedSpiralPage : ContentPage
{
    const double cycleTime = 250;       // in milliseconds

    SKCanvasView canvasView;
    Stopwatch stopwatch = new Stopwatch();
    bool pageIsActive;
    float dashPhase;

    public AnimatedSpiralPage()
    {
        Title = "Animated Spiral";

        canvasView = new SKCanvasView();
        canvasView.PaintSurface += OnCanvasViewPaintSurface;
        Content = canvasView;
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();
        pageIsActive = true;
        stopwatch.Start();

        Device.StartTimer(TimeSpan.FromMilliseconds(33), () =>
        {
            double t = stopwatch.Elapsed.TotalMilliseconds % cycleTime / cycleTime;
            dashPhase = (float)(10 * t);
            canvasView.InvalidateSurface();

            if (!pageIsActive)
            {
                stopwatch.Stop();
            }

            return pageIsActive;
        });
    }
    ···  
}

Bien sûr, vous devrez exécuter le programme pour voir l’animation :

Capture d’écran triple de la page Spirale animée