Partager via


Lignes et extrémités de trait

Découvrez comment utiliser SkiaSharp pour dessiner des lignes avec différentes majuscules de trait

Dans SkiaSharp, le rendu d’une seule ligne est très différent du rendu d’une série de lignes droites connectées. Même lorsque vous dessinez des traits simples, il est souvent nécessaire de donner aux lignes une largeur de trait particulière. À mesure que ces lignes deviennent plus larges, l’apparence des extrémités des lignes devient également importante. L’apparence de la fin de la ligne est appelée capuchon de trait :

Les trois options de limite de trait

Pour dessiner des lignes uniques, SKCanvas définit une méthode simple DrawLine dont les arguments indiquent les coordonnées de début et de fin de la ligne avec un SKPaint objet :

canvas.DrawLine (x0, y0, x1, y1, paint);

Par défaut, la StrokeWidth propriété d’un objet nouvellement instancié SKPaint est 0, qui a le même effet que la valeur 1 dans le rendu d’une ligne d’un pixel en épaisseur. Cela semble très mince sur les appareils haute résolution tels que les téléphones, donc vous voudrez probablement définir la StrokeWidth valeur sur une valeur plus élevée. Mais une fois que vous commencez à dessiner des lignes d’une épaisseur sizable, qui soulève un autre problème : Comment les débuts et les extrémités de ces lignes épaisses doivent-elles être rendues ?

L’apparence des débuts et des extrémités des lignes est appelée un capuchon de ligne ou, dans Skia, un capuchon de trait. Le mot « cap » dans ce contexte fait référence à un type de chapeau , quelque chose qui se trouve à la fin de la ligne. Vous définissez la StrokeCap propriété de l’objet SKPaint sur l’un des membres suivants de l’énumération SKStrokeCap :

  • Butt (valeur par défaut)
  • Square
  • Round

Ceux-ci sont mieux illustrés avec un exemple de programme. La section Lignes et chemins SkiaSharp de l’exemple de programme commence par une page intitulée Stroke Caps en fonction de la StrokeCapsPage classe. Cette page définit un gestionnaire d’événements qui effectue une PaintSurface boucle dans les trois membres de l’énumération SKStrokeCap , affichant à la fois le nom du membre d’énumération et dessinant une ligne à l’aide de cette limite de trait :

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

    canvas.Clear();

    SKPaint textPaint = new SKPaint
    {
        Color = SKColors.Black,
        TextSize = 75,
        TextAlign = SKTextAlign.Center
    };

    SKPaint thickLinePaint = new SKPaint
    {
        Style = SKPaintStyle.Stroke,
        Color = SKColors.Orange,
        StrokeWidth = 50
    };

    SKPaint thinLinePaint = new SKPaint
    {
        Style = SKPaintStyle.Stroke,
        Color = SKColors.Black,
        StrokeWidth = 2
    };

    float xText = info.Width / 2;
    float xLine1 = 100;
    float xLine2 = info.Width - xLine1;
    float y = textPaint.FontSpacing;

    foreach (SKStrokeCap strokeCap in Enum.GetValues(typeof(SKStrokeCap)))
    {
        // Display text
        canvas.DrawText(strokeCap.ToString(), xText, y, textPaint);
        y += textPaint.FontSpacing;

        // Display thick line
        thickLinePaint.StrokeCap = strokeCap;
        canvas.DrawLine(xLine1, y, xLine2, y, thickLinePaint);

        // Display thin line
        canvas.DrawLine(xLine1, y, xLine2, y, thinLinePaint);
        y += 2 * textPaint.FontSpacing;
    }
}

Pour chaque membre de l’énumération SKStrokeCap , le gestionnaire dessine deux lignes, une avec une épaisseur de trait de 50 pixels et une autre ligne positionnée sur le dessus avec une épaisseur de trait de deux pixels. Cette deuxième ligne est destinée à illustrer le début et la fin géométriques de la ligne indépendamment de l’épaisseur de trait et d’un capuchon de trait :

Capture d’écran triple de la page Caps du trait

Comme vous pouvez le voir, les Square capuchons et Round traits étendent efficacement la longueur de la ligne par la moitié de la largeur du trait au début de la ligne et à nouveau à la fin. Cette extension devient importante lorsqu’il est nécessaire de déterminer les dimensions d’un objet graphique rendu.

La SKCanvas classe inclut également une autre méthode pour dessiner plusieurs lignes qui sont quelque peu particulières :

DrawPoints (SKPointMode mode, points, paint)

Le points paramètre est un tableau de SKPoint valeurs et mode est membre de l’énumération SKPointMode , qui a trois membres :

  • Points pour afficher les points individuels
  • Lines pour connecter chaque paire de points
  • Polygon pour connecter tous les points consécutifs

La page Plusieurs lignes illustre cette méthode. Le fichier MultipleLinesPage.xaml instancie deux Picker vues qui vous permettent de sélectionner un membre de l’énumération SKPointMode et un membre de l’énumération SKStrokeCap :

<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.MultipleLinesPage"
             Title="Multiple Lines">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Picker x:Name="pointModePicker"
                Title="Point Mode"
                Grid.Row="0"
                Grid.Column="0"
                SelectedIndexChanged="OnPickerSelectedIndexChanged">
            <Picker.ItemsSource>
                <x:Array Type="{x:Type skia:SKPointMode}">
                    <x:Static Member="skia:SKPointMode.Points" />
                    <x:Static Member="skia:SKPointMode.Lines" />
                    <x:Static Member="skia:SKPointMode.Polygon" />
                </x:Array>
            </Picker.ItemsSource>
            <Picker.SelectedIndex>
                0
            </Picker.SelectedIndex>
        </Picker>

        <Picker x:Name="strokeCapPicker"
                Title="Stroke Cap"
                Grid.Row="0"
                Grid.Column="1"
                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>

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

Notez que les déclarations d’espace de noms SkiaSharp sont un peu différentes, car l’espace SkiaSharp de noms est nécessaire pour référencer les membres des SKPointMode et SKStrokeCap énumérations. Le SelectedIndexChanged gestionnaire pour les deux Picker vues invalide simplement l’objet SKCanvasView :

void OnPickerSelectedIndexChanged(object sender, EventArgs args)
{
    if (canvasView != null)
    {
        canvasView.InvalidateSurface();
    }
}

Ce gestionnaire doit case activée pour l’existence de l’objetSKCanvasView, car le gestionnaire d’événements est d’abord appelé lorsque la SelectedIndex propriété du Picker fichier XAML est définie sur 0 et qui se produit avant l’instanciation.SKCanvasView

Le PaintSurface gestionnaire obtient les deux valeurs d’énumération des Picker vues :

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

    canvas.Clear();

    // Create an array of points scattered through the page
    SKPoint[] points = new SKPoint[10];

    for (int i = 0; i < 2; i++)
    {
        float x = (0.1f + 0.8f * i) * info.Width;

        for (int j = 0; j < 5; j++)
        {
            float y = (0.1f + 0.2f * j) * info.Height;
            points[2 * j + i] = new SKPoint(x, y);
        }
    }

    SKPaint paint = new SKPaint
    {
        Style = SKPaintStyle.Stroke,
        Color = SKColors.DarkOrchid,
        StrokeWidth = 50,
        StrokeCap = (SKStrokeCap)strokeCapPicker.SelectedItem
    };

    // Render the points by calling DrawPoints
    SKPointMode pointMode = (SKPointMode)pointModePicker.SelectedItem;
    canvas.DrawPoints(pointMode, points, paint);
}

Les captures d’écran montrent une variété de Picker sélections :

Capture d’écran triple de la page Plusieurs lignes

L’i Téléphone à gauche montre comment le SKPointMode.Points membre d’énumération provoque DrawPoints le rendu de chacun des points du SKPoint tableau sous la forme d’un carré si la limite de ligne est Butt ou Square. Les cercles sont affichés si la limite de ligne est Round.

La capture d’écran Android montre le résultat du SKPointMode.Lines. La DrawPoints méthode dessine une ligne entre chaque paire de valeurs, à l’aide de la limite de SKPoint ligne spécifiée, dans ce cas Round.

Lorsque vous utilisez SKPointMode.Polygonplutôt , une ligne est dessinée entre les points successifs du tableau, mais si vous regardez très attentivement, vous verrez que ces lignes ne sont pas connectées. Chacune de ces lignes distinctes commence et se termine par la limite de ligne spécifiée. Si vous sélectionnez les Round majuscules, les lignes peuvent sembler connectées, mais elles ne sont vraiment pas connectées.

Si les lignes sont connectées ou non connectées est un aspect crucial de l’utilisation des chemins graphiques.