Čá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:
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:
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
:
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 Round
zakonč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.