Linee ed estremità dei trattiLines and Stroke Caps

Scaricare l'esempio scaricare l'esempioDownload Sample Download the sample

Informazioni su come usare SkiaSharp per disegnare linee con estremità dei tratti diversiLearn how to use SkiaSharp to draw lines with different stroke caps

In SkiaSharp, il rendering di una singola riga è molto diverso dal rendering di una serie di linee rette collegate.In SkiaSharp, rendering a single line is very different from rendering a series of connected straight lines. Anche quando si disegnano le singole righe, tuttavia, è spesso necessario assegnare le righe uno spessore particolare.Even when drawing single lines, however, it's often necessary to give the lines a particular stroke width. Man mano che queste righe diventano più ampie, diventa importante anche l'aspetto delle entità finali delle righe.As these lines become wider, the appearance of the ends of the lines also becomes important. L'aspetto della fine della riga viene chiamato il estremità della traccia:The appearance of the end of the line is called the stroke cap:

Per disegnare singole righe, SKCanvas definisce una semplice DrawLine metodo cui argomenti indicano l'inizio e fine coordinate della riga con un SKPaint oggetto:For drawing single lines, SKCanvas defines a simple DrawLine method whose arguments indicate the starting and ending coordinates of the line with an SKPaint object:

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

Per impostazione predefinita, il StrokeWidth proprietà di una nuova istanza SKPaint oggetto è 0, che ha lo stesso effetto di un valore di 1 il rendering di una riga di un pixel in spessore.By default, the StrokeWidth property of a newly instantiated SKPaint object is 0, which has the same effect as a value of 1 in rendering a line of one pixel in thickness. Questo valore viene visualizzato fette molto sottile dispositivi ad alta risoluzione, ad esempio telefoni, pertanto è opportuno impostare il StrokeWidth su un valore maggiore.This appears very thin on high-resolution devices such as phones, so you'll probably want to set the StrokeWidth to a larger value. Tuttavia, una volta che si inizia a disegnare righe di uno spessore considerevole, viene generato un altro problema: Come devono essere visualizzati i punti di inizio e di fine di queste linee spesse?But once you start drawing lines of a sizable thickness, that raises another issue: How should the starts and ends of these thick lines be rendered?

L'aspetto dell'avvio e fine delle righe viene chiamato un estremità della linea o, in Skia, un estremità della traccia.The appearance of the starts and ends of lines is called a line cap or, in Skia, a stroke cap. La parola "limite" in questo contesto si riferisce a un tipo di hat — qualcosa che si trova all'estremità della linea.The word "cap" in this context refers to a kind of hat — something that sits on the end of the line. È impostato il StrokeCap proprietà della SKPaint oggetto in uno dei seguenti membri del SKStrokeCap enumerazione:You set the StrokeCap property of the SKPaint object to one of the following members of the SKStrokeCap enumeration:

  • Butt (predefinito)Butt (the default)
  • Square
  • Round

Questi vengono illustrate più chiaramente con un programma di esempio.These are best illustrated with a sample program. Il SkiaSharp linee e i percorsi sezione del SkiaSharpFormsDemos programma inizia con una pagina intitolata estremità dei tratti base il StrokeCapsPage classe.The SkiaSharp Lines and Paths section of the SkiaSharpFormsDemos program begins with a page titled Stroke Caps based on the StrokeCapsPage class. Questa pagina definisce una PaintSurface gestore eventi che consente di scorrere i tre membri del SKStrokeCap enumerazione, la visualizzazione sia il nome del membro dell'enumerazione e tracciare una linea con tale limite di traccia:This page defines a PaintSurface event handler that loops through the three members of the SKStrokeCap enumeration, displaying both the name of the enumeration member and drawing a line using that stroke cap:

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

Per ogni membro del SKStrokeCap enumerazione, il gestore disegnate due linee, uno con uno spessore del tratto pari a 50 pixel e un'altra riga posizionata nella parte superiore e con uno spessore del tratto di due pixel.For each member of the SKStrokeCap enumeration, the handler draws two lines, one with a stroke thickness of 50 pixels and another line positioned on top with a stroke thickness of two pixels. Questa seconda riga è lo scopo di illustrare geometrica inizio e alla fine della riga di indipendenti di spessore della linea e un limite di traccia:This second line is intended to illustrate the geometric start and end of the line independent of the line thickness and a stroke cap:

Come può notare, il Square e Round estremità dei tratti estendere in modo efficace la lunghezza della riga per metà della larghezza di tratto all'inizio della riga e di nuovo alla fine.As you can see, the Square and Round stroke caps effectively extend the length of the line by half the stroke width at the beginning of the line and again at the end. Questa estensione diventa importante quando è necessario determinare le dimensioni di un oggetto di rendering della grafica.This extension becomes important when it's necessary to determine the dimensions of a rendered graphics object.

Il SKCanvas classe include anche un altro metodo per la creazione di più righe che è un po' particolare:The SKCanvas class also includes another method for drawing multiple lines that is somewhat peculiar:

DrawPoints (SKPointMode mode, points, paint)

Il points parametro è una matrice di SKPoint i valori e mode è un membro del SKPointMode enumerazione, che dispone di tre membri:The points parameter is an array of SKPoint values and mode is a member of the SKPointMode enumeration, which has three members:

  • Points Per eseguire il rendering dei singoli puntiPoints to render the individual points
  • Lines Per connettersi ogni coppia di puntiLines to connect each pair of points
  • Polygon Per connettere tutti i punti consecutiviPolygon to connect all consecutive points

Il più righe pagina viene illustrato questo metodo.The Multiple Lines page demonstrates this method. Il MultipleLinesPage.xaml file crea un'istanza di due Picker viste che consentono di selezionare un membro del SKPointMode enumerazione e un membro del SKStrokeCap enumerazione:The MultipleLinesPage.xaml file instantiates two Picker views that let you select a member of the SKPointMode enumeration and a member of the SKStrokeCap enumeration:

<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>

Si noti che le dichiarazioni dello spazio dei nomi di SkiaSharp sono un po' diverso perché le SkiaSharp dello spazio dei nomi è necessaria per fare riferimento ai membri del SKPointMode e SKStrokeCap enumerazioni.Notice that the SkiaSharp namespace declarations are a little different because the SkiaSharp namespace is needed to reference the members of the SKPointMode and SKStrokeCap enumerations. Il SelectedIndexChanged gestore per entrambi Picker viste semplicemente invalida il SKCanvasView oggetto:The SelectedIndexChanged handler for both Picker views simply invalidates the SKCanvasView object:

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

Deve verificare l'esistenza di questo gestore il SKCanvasView oggetto perché è il primo gestore dell'evento viene chiamato quando il SelectedIndex proprietà delle Picker è impostato su 0 nel file XAML, e che si verifica prima il SKCanvasView è stata creata un'istanza.This handler needs to check for the existence of the SKCanvasView object because the event handler is first called when the SelectedIndex property of the Picker is set to 0 in the XAML file, and that occurs before the SKCanvasView has been instantiated.

Il PaintSurface gestore ottiene i due valori di enumerazione dal Picker viste:The PaintSurface handler obtains the two enumeration values from the Picker views:

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

Le schermate illustrano un'ampia gamma di Picker selezioni:The screenshots show a variety of Picker selections:

L'iPhone a sinistra illustra come la SKPointMode.Points fa sì che il membro di enumerazione DrawPoints per eseguire il rendering di ognuno dei punti nel SKPoint matrice come un quadrato se è il delimitatore di linea Butt o Square.The iPhone at the left shows how the SKPointMode.Points enumeration member causes DrawPoints to render each of the points in the SKPoint array as a square if the line cap is Butt or Square. Cerchi vengono sottoposti a rendering se è il delimitatore di linea Round.Circles are rendered if the line cap is Round.

Quando si usa invece SKPointMode.Lines, come illustrato nella schermata Android nel centro, il DrawPoints metodo disegna una linea tra ogni coppia di SKPoint i valori, utilizzando la terminazione di riga specificata, in questo caso Round.When you instead use SKPointMode.Lines, as shown on the Android screen in the center, the DrawPoints method draws a line between each pair of SKPoint values, using the specified line cap, in this case Round.

La schermata UWP Mostra il risultato del SKPointMode.Polygon valore.The UWP screenshot shows the result of the SKPointMode.Polygon value. Viene tracciata una linea tra i punti consecutivi nella matrice, ma se si osserva attentamente, si noterà che le righe seguenti non sono connessi.A line is drawn between the successive points in the array, but if you look very closely, you'll see that these lines are not connected. Ognuna di queste righe separate inizia e termina con la terminazione di riga specificato.Each of these separate lines starts and ends with the specified line cap. Se si seleziona il Round BLOC MAIUSC, le righe potrebbero sembrare siano connessi, ma davvero non sono connesse.If you select the Round caps, the lines might appear to be connected, but they're really not connected.

Se le righe sono connesso o non connesso è un aspetto fondamentale di utilizzo dei percorsi di elementi grafici.Whether lines are connected or not connected is a crucial aspect of working with graphics paths.