Sdílet prostřednictvím


Čáry a zakončení tahů

Naučte se používat SkiaSharp k kreslení čar s různými zakončeními tahů.

V skiaSharpu se vykreslení jedné čáry velmi liší od vykreslení řady propojených rovných čar. I když ale kreslíte jednotlivé čáry, je často nutné dát čarám určitou šířku tahu. Jak se tyto čáry rozšíří, vzhled konců čar je také důležitý. Vzhled konce čáry se nazývá zakončení tahu:

Možnosti tří tahů

Pro kreslení jednoduchých čar definuje jednoduchou DrawLine metodu, SKCanvas jejíž argumenty označují počáteční a koncové souřadnice čáry s objektemSKPaint:

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

Ve výchozím nastavení je StrokeWidth vlastnost nově vytvořený SKPaint objekt 0, která má stejný účinek jako hodnota 1 při vykreslení čáry o jedné pixelové tloušťkě. Na zařízeních s vysokým rozlišením, jako jsou telefony, to vypadá velmi dynamicky, takže pravděpodobně budete chtít nastavit StrokeWidth větší hodnotu. Ale jakmile začnete kreslit čáry s možnou tloušťkou, která vyvolává další problém: Jak by se měly vykreslovat začátek a konce těchto silných čar?

Vzhled startů a konců čar se nazývá zakončení čáry nebo v Skia čepice tahu. Slovo "cap" v tomto kontextu odkazuje na druh klobouku – něco, co se nachází na konci řádku. Vlastnost objektu nastavíte StrokeCap na jeden z následujících členů výčtuSKStrokeCap:SKPaint

  • Butt (výchozí)
  • Square
  • Round

Ty jsou nejlépe ilustrované ukázkovým programem. Oddíl Čáry a cesty skiaSharp ukázkového programu začíná stránkou s názvem Tah caps na StrokeCapsPage základě třídy. Tato stránka definuje obslužnou rutinu PaintSurface události, která prochází třemi členy SKStrokeCap výčtu a zobrazuje jak název člena výčtu, tak vykreslení čáry pomocí tohoto zakončení tahů:

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

Pro každý člen výčtu SKStrokeCap obslužná rutina nakreslí dvě čáry, jednu s tloušťkou tahu 50 pixelů a jinou čárou umístěnou nahoře s tloušťkou tahu dvou pixelů. Tato druhá čára má znázornit geometrický začátek a konec čáry nezávisle na tloušťkě čáry a zakončení tahu:

Trojitý snímek obrazovky se stránkou Caps (Caps) tahů

Jak vidíte, Square čepice a Round tahy efektivně rozšiřují délku čáry o polovinu šířky tahu na začátku čáry a znovu na konci. Toto rozšíření je důležité, když je nutné určit rozměry vykreslovaného grafického objektu.

Třída SKCanvas obsahuje také další metodu kreslení více čar, které jsou poněkud zvláštní:

DrawPoints (SKPointMode mode, points, paint)

Parametr points je pole SKPoint hodnot a mode je členem výčtu SKPointMode , který má tři členy:

  • Points vykreslení jednotlivých bodů
  • Lines pro připojení jednotlivých dvojic bodů
  • Polygon propojení všech po sobě jdoucích bodů

Stránka Více řádků ukazuje tuto metodu. Soubor MultipleLinesPage.xaml vytvoří instanci dvou Picker zobrazení, která umožňují vybrat člen SKPointMode výčtu a člen výčtu 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>

Všimněte si, že deklarace oboru názvů SkiaSharp jsou trochu jiné, protože SkiaSharp obor názvů je potřeba odkazovat na členy SKPointMode a SKStrokeCap výčty. Obslužná rutina SelectedIndexChanged pro obě Picker zobrazení jednoduše zneplatní SKCanvasView objekt:

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

Tato obslužná rutina musí zkontrolovat existenci objektu SKCanvasView , protože obslužná rutina události je nejprve volána, když SelectedIndex je vlastnost objektu Picker nastavena na hodnotu 0 v souboru XAML a která nastane před SKCanvasView vytvořením instance.

Obslužná PaintSurface rutina získá ze zobrazení dvě hodnoty výčtu Picker :

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

Snímky obrazovky zobrazují různé výběry Picker :

Trojitý snímek obrazovky se stránkou Více řádků

I Telefon vlevo ukazuje, jak SKPointMode.Points člen výčtu způsobí DrawPoints vykreslení každého bodu v SKPoint matici jako čtverec, pokud je Butt zakončení čáry nebo Square. Kruhy jsou vykresleny, pokud je Roundzakončení čáry .

Snímek obrazovky Androidu ukazuje výsledek SKPointMode.Lines. Metoda DrawPoints nakreslí čáru mezi jednotlivými dvojicemi SKPoint hodnot pomocí zadaného zakončení čáry v tomto případě Round.

Když místo toho použijete SKPointMode.Polygon, čára se nakreslí mezi po sobě jdoucími body v matici, ale pokud se podíváte velmi pozorně, uvidíte, že tyto čáry nejsou propojené. Každý ztěchtoch Pokud vyberete Round caps, čáry se můžou zdát propojené, ale ve skutečnosti nejsou propojené.

Bez ohledu na to, jestli jsou čáry propojené nebo nejsou propojené, je zásadní aspekt práce s grafickými cestami.