Kropki i kreski w SkiaSharp
Opanowanie zawiłości rysunku kropkowanych i przerywanych linii w SkiaSharp
SkiaSharp umożliwia rysowanie linii, które nie są solidne, ale zamiast tego składają się z kropek i kreski:
Można to zrobić za pomocą efektu ścieżki, czyli wystąpienia SKPathEffect
klasy ustawionej na PathEffect
właściwość SKPaint
. Możesz utworzyć efekt ścieżki (lub połączyć efekty ścieżki) przy użyciu jednej ze statycznych metod tworzenia zdefiniowanych przez SKPathEffect
. (SKPathEffect
jest jednym z sześciu efektów obsługiwanych przez SkiaSharp; pozostałe są opisane w sekcji SkiaSharp Effect.
Aby narysować linie kropkowane lub przerywane, należy użyć metody statycznej SKPathEffect.CreateDash
. Istnieją dwa argumenty: jest to tablica wartości wskazująca długość kropki float
i kreski oraz długość spacji między nimi. Ta tablica musi mieć parzystą liczbę elementów i powinna istnieć co najmniej dwa elementy. (Może istnieć zero elementów w tablicy, ale powoduje to utworzenie linii stałej). Jeśli istnieją dwa elementy, pierwszy to długość kropki lub kreski, a druga to długość szczeliny przed następną kropką lub kreską. Jeśli istnieje więcej niż dwa elementy, to są w następującej kolejności: długość kreski, długość szczeliny, długość kreski, długość szczeliny i tak dalej.
Ogólnie rzecz biorąc, należy ustawić kreskę i długość odstępu wielokrotność szerokości pociągnięcia. Jeśli na przykład szerokość pociągnięcia wynosi 10 pikseli, tablica { 10, 10 } narysuje linię kropkowaną, w której kropki i luki mają taką samą długość jak grubość pociągnięcia.
Jednak StrokeCap
ustawienie SKPaint
obiektu wpływa również na te kropki i kreski. Jak zobaczysz wkrótce, ma to wpływ na elementy tej tablicy.
Linie kropkowane i kreskowane są pokazane na stronie Kropki i Kreski . Plik DotsAndDashesPage.xaml tworzy wystąpienie dwóch Picker
widoków, jeden umożliwiający wybranie limitu pociągnięcia, a drugi do wybrania tablicy kreskowej:
<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>
Pierwsze trzy elementy w założyć dashArrayPicker
, że szerokość pociągnięcia wynosi 10 pikseli. Tablica { 10, 10 } jest dla linii kropkowanej, { 30, 10 } jest dla linii kreskowanej, a { 10, 10, 30, 10 } jest dla linii kropkowej i kreski. (Pozostałe trzy zostaną omówione wkrótce).
Plik DotsAndDashesPage
związany z kodem zawiera procedurę PaintSurface
obsługi zdarzeń i kilka procedur pomocnika umożliwiających uzyskiwanie Picker
dostępu do widoków:
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 poniższych zrzutach ekranu na ekranie systemu iOS po lewej stronie jest wyświetlana linia kropkowana:
Jednak ekran systemu Android ma również wyświetlać linię kropkowaną przy użyciu tablicy { 10, 10 }, ale zamiast tego linia jest solidna. Co się stało? Problem polega na tym, że ekran systemu Android ma również ustawienie limitów pociągnięcia .Square
Rozszerza to wszystkie kreski o połowę szerokości pociągnięcia, powodując ich wypełnienie luk.
Aby obejść ten problem podczas korzystania z czapki Square
pociągnięcia lub Round
, należy zmniejszyć długość kreski w tablicy o długość pociągnięcia (czasami powodując długość kreski 0) i zwiększyć długość odstępu o długość pociągnięcia. W ten sposób zostały obliczone ostatnie trzy tablice kreskowe w Picker
pliku XAML:
- { 10, 10 } staje się { 0, 20 } dla kropkowanej linii
- { 30, 10 } staje się { 20, 20 } dla linii kreskowanej
- { 10, 10, 30, 10 } staje się { 0, 20, 20, 20} dla linii kropkowanej i przerywanej
Ekran platformy UWP pokazuje, że linia kropkowana i przerywana dla limitu pociągnięcia .Round
Czapka Round
pociągnięć często daje najlepszy wygląd kropek i kreski w grubych liniach.
Do tej pory nie wspomniano o drugim parametrze metody SKPathEffect.CreateDash
. Ten parametr ma nazwę phase
i odwołuje się do przesunięcia we wzorcu kropki i kreski na początku wiersza. Jeśli na przykład tablica kreskowa to { 10, 10 } i phase
ma wartość 10, wiersz zaczyna się od luki, a nie kropki.
Jedną z interesujących zastosowań parametru phase
jest animacja. Strona Animowana spirala jest podobna do strony Archimedean Spiral, z tą różnicą, że AnimatedSpiralPage
klasa animuje phase
parametr przy użyciu 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;
});
}
···
}
Oczywiście musisz uruchomić program, aby zobaczyć animację: