Tečky a pomlčky ve skiaSharpu
Zvládnutí složitých kreslicích tečkovaných a přerušovaných čar ve SkiaSharpu
SkiaSharp umožňuje kreslit čáry, které nejsou plné, ale místo toho se skládají z tečk a pomlček:
Provedete to s cestou efekt, což je instance SKPathEffect
třídy, kterou jste nastavili na PathEffect
vlastnost SKPaint
. Efekt cesty (nebo zkombinování efektů cesty) můžete vytvořit pomocí jedné ze statických metod vytváření definovaných .SKPathEffect
(SKPathEffect
je jedním ze šesti účinků podporovaných skiaSharpem; ostatní jsou popsány v části SkiaSharp Efekt.)
Pokud chcete nakreslit tečkované nebo přerušované čáry, použijte statickou metodu SKPathEffect.CreateDash
. Existují dva argumenty: První je pole float
hodnot, které označují délky tečk a pomlček a délku mezer mezi nimi. Toto pole musí mít sudý počet prvků a měl by existovat alespoň dva prvky. (Pole může obsahovat nula prvků, ale výsledkem je plná čára.) Pokud existují dva prvky, první je délka tečky nebo pomlčky a druhá je délka mezery před další tečkou nebo pomlčkou. Pokud existuje více než dva prvky, pak jsou v tomto pořadí: délka pomlčky, délka mezery, délka pomlčky, délka mezery atd.
Obecně platí, že chcete, aby délka přerušované čáry a mezery byla násobkem šířky tahu. Pokud je šířka tahu 10 pixelů, bude například matice { 10, 10 } nakreslit tečkovanou čáru, kde tečky a mezery mají stejnou délku jako tloušťka tahu.
Nastavení StrokeCap
objektu SKPaint
však také ovlivňuje tyto tečky a pomlčky. Jak uvidíte krátce, má to vliv na prvky tohoto pole.
Tečkované a přerušované čáry jsou znázorněny na stránce Tečky a Pomlčky . Soubor DotsAndDashesPage.xaml vytvoří instanci dvou Picker
zobrazení, jedno pro výběr zakončení tahů a druhé pro výběr pole pomlček:
<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>
První tři položky v předpokladu dashArrayPicker
, že šířka tahu je 10 pixelů. Pole { 10, 10 } je pro tečkovanou čáru, { 30, 10 } je pro přerušovanou čáru a { 10, 10, 30, 10 } je pro tečkovanou a pomlčkovou čáru. (Další tři budou probírané krátce.)
Soubor DotsAndDashesPage
kódu obsahuje obslužnou rutinu PaintSurface
události a několik pomocných rutin pro přístup k Picker
zobrazení:
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;
}
Na následujících snímcích obrazovky s iOSem na levé straně je tečkovaná čára:
Obrazovka Androidu ale má také zobrazit tečkovanou čáru pomocí pole { 10, 10 }, ale místo toho je čára plná. Co se stalo? Problém je, že obrazovka Android má také nastavení tahů caps nastavení Square
. Tím se rozšíří všechny pomlčky o polovinu šířky tahu, což způsobí, že zaplní mezery.
Chcete-li tento problém obejít při použití zakončení tahu Square
nebo Round
, je nutné snížit délky pomlčky v matici o délku tahu (někdy vede k pomlčky délky 0) a zvýšit délku mezery o délku tahu. Takto se vypočítaly poslední tři pomlčky v Picker
souboru XAML:
- { 10, 10 } se stane { 0, 20 } pro tečkovanou čáru.
- { 30, 10 } se stane { 20, 20 } pro přerušovanou čáru.
- { 10, 10, 30, 10 } se změní na { 0, 20, 20, 20} pro tečkovanou a přerušovanou čáru.
Obrazovka UPW ukazuje tečkovanou a přerušovanou čáru pro čepici tahu Round
. Čepice Round
tahů často dává nejlepší vzhled teček a pomlček v silných čarách.
Zatím nebyla provedena žádná zmínka o druhém parametru metody SKPathEffect.CreateDash
. Tento parametr má název phase
a odkazuje na posun v rámci vzoru tečky a pomlčky pro začátek čáry. Pokud je například matici pomlčky { 10, 10 } a phase
je 10, začíná čára mezerou místo tečky.
Jedna zajímavá aplikace parametru phase
je v animaci. Animovaný spirála stránka je podobná Archimedean Spirála stránka s tím rozdílem, že AnimatedSpiralPage
třída animuje phase
parametr pomocí Xamarin.FormsDevice.Timer
metody:
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;
});
}
···
}
Samozřejmě budete muset spustit program, abyste viděli animaci: