Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Meistern Sie die Ungenauigkeiten des Zeichnens gepunkteter und gestrichelter Linien in SkiaSharp
Mit SkiaSharp können Sie Linien zeichnen, die nicht einfarbig sind, sondern aus Punkten und Strichen bestehen:

Dazu verwenden Sie einen Pfadeffekt, bei dem es sich um eine Instanz der SKPathEffect Klasse handelt, die Sie auf die PathEffect Eigenschaft von SKPaintfestgelegt haben. Sie können einen Pfadeffekt (oder Pfadeffekte kombinieren) mithilfe einer der statischen Erstellungsmethoden erstellen, die von SKPathEffect. (SKPathEffect ist einer von sechs Effekten, die von SkiaSharp unterstützt werden; die anderen werden im Abschnitt SkiaSharp Effect beschrieben.)
Zum Zeichnen gepunkteter oder gestrichelter Linien verwenden Sie die SKPathEffect.CreateDash statische Methode. Es gibt zwei Argumente: Dies ist zuerst ein Array von float Werten, das die Längen der Punkte und Bindestriche und die Länge der Zwischenräume angibt. Dieses Array muss über eine gerade Anzahl von Elementen verfügen, und es sollten mindestens zwei Elemente vorhanden sein. (Es können null Elemente im Array vorhanden sein, die jedoch zu einer durchgezogenen Linie führen.) Wenn zwei Elemente vorhanden sind, ist die erste die Länge eines Punkts oder Gedankenstrichs, und die zweite ist die Länge des Abstands vor dem nächsten Punkt oder Strich. Wenn mehr als zwei Elemente vorhanden sind, sind sie in dieser Reihenfolge angeordnet: Strichlänge, Abstandslänge, Strichlänge, Strichlänge, Abstandslänge usw.
Im Allgemeinen sollten Sie die Strich- und Abstandslängen auf ein Vielfaches der Strichbreite festlegen. Wenn die Strichbreite beispielsweise 10 Pixel beträgt, zeichnet das Array {10, 10 } eine gepunktete Linie, wobei die Punkte und Lücken dieselbe Länge wie die Strichstärke aufweisen.
StrokeCap Die Einstellung des SKPaint Objekts wirkt sich jedoch auch auf diese Punkte und Gedankenstriche aus. Wie Sie in Kürze sehen, wirkt sich dies auf die Elemente dieses Arrays aus.
Gepunktete und gestrichelte Linien werden auf der Seite "Punkte" und "Striche" veranschaulicht. Die Datei DotsAndDashesPage.xaml instanziiert zwei Picker Ansichten, eine, mit der Sie eine Strichkappe und die zweite auswählen können, um ein Stricharray auszuwählen:
<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>
Bei den ersten drei Elementen wird dashArrayPicker davon ausgegangen, dass die Strichbreite 10 Pixel beträgt. Das Array {10, 10 } ist für eine gepunktete Linie, { 30, 10 } für eine gestrichelte Linie, und { 10, 10, 30, 10 } ist für eine Punkt- und Strichlinie vorgesehen. (Die anderen drei werden in Kürze erörtert.)
Die DotsAndDashesPage CodeBehind-Datei enthält den PaintSurface Ereignishandler und einige Hilfsroutinen für den Zugriff auf die Picker Ansichten:
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;
}
In den folgenden Screenshots zeigt der iOS-Bildschirm ganz links eine gepunktete Linie:
Der Android-Bildschirm soll jedoch auch eine gepunktete Linie mit dem Array { 10, 10 } anzeigen, aber stattdessen ist die Linie einfarbig. Was ist passiert? Das Problem besteht darin, dass der Android-Bildschirm auch über eine Strichkappeneinstellung verfügt Square. Dadurch werden alle Striche um die Hälfte der Strichbreite erweitert, wodurch sie die Lücken füllen.
Um dieses Problem bei Verwendung einer Strichkappe von Square oder Roundzu umgehen, müssen Sie die Strichlängen im Array um die Strichlänge (manchmal zu einer Strichlänge von 0) verringern und die Abstandslängen um die Strichlänge erhöhen. So wurden die letzten drei Stricharrays in der Picker XAML-Datei berechnet:
- { 10, 10 } wird { 0, 20 } für eine gepunktete Linie
- { 30, 10 } wird { 20, 20 } für eine gestrichelte Linie
- { 10, 10, 30, 10 } wird { 0, 20, 20, 20} für eine gepunktete und gestrichelte Linie
Der UWP-Bildschirm zeigt die gepunktete und gestrichelte Linie für eine Strichkappe von Round. Die Round Strichkappe gibt häufig das beste Erscheinungsbild von Punkten und Gedankenstrichen in dicken Linien.
Bisher wurde kein Erwähnung aus dem zweiten Parameter an die SKPathEffect.CreateDash Methode gemacht. Dieser Parameter wird benannt phase und bezieht sich auf einen Offset innerhalb des Punkt-und-Strich-Musters für den Anfang der Linie. Wenn z. B. das Stricharray {10, 10 } und der phase Wert 10 ist, beginnt die Linie mit einer Lücke und nicht mit einem Punkt.
Eine interessante Anwendung des phase Parameters ist in einer Animation. Die Seite "Animierte Spirale" ähnelt der Archimedean Spirale-Seite, mit der Ausnahme, dass die AnimatedSpiralPage Klasse den phase Parameter mithilfe der Xamarin.FormsDevice.Timer Methode animiert:
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;
});
}
···
}
Natürlich müssen Sie das Programm tatsächlich ausführen, um die Animation anzuzeigen:

