SkiaSharp 中的點和虛線
掌握在 SkiaSharp 中繪製虛線和虛線的複雜
SkiaSharp 可讓您繪製不是實心的線條,而是由點和虛線組成:
您可以使用路徑效果來執行此動作,這是您設定為 PathEffect
屬性之 類別的SKPaint
實例SKPathEffect
。 您可以使用 所 SKPathEffect
定義的其中一個靜態建立方法,建立路徑效果(或結合路徑效果)。 (SKPathEffect
是 SkiaSharp 支援的六個效果之一;其他效果則描述於 SkiaSharp 效果一節中。
若要繪製虛線或虛線,您可以使用 SKPathEffect.CreateDash
靜態方法。 有兩個自變數:第一個是值陣列 float
,指出點和虛線的長度,以及兩者之間空格的長度。 這個陣列必須有偶數個元素,而且至少應該有兩個元素。 (陣列中可以有零個專案,但會產生實線。如果有兩個元素,第一個是點或虛線的長度,第二個是下一個點或虛線之前的間距長度。 如果有兩個以上的元素,則其順序如下:虛線長度、間距長度、虛線長度、間距長度等等。
一般而言,您會想要讓虛線和間距長度成為筆劃寬度的倍數。 例如,如果筆劃寬度為 10 像素,則陣列 { 10, 10 } 會繪製虛線,其中點和間距與筆劃粗細的長度相同。
不過, StrokeCap
對象的設定 SKPaint
也會影響這些點和虛線。 如您所見,這會影響此陣列的元素。
虛線和虛線會在 [點] 和 [虛線] 頁面上示範。 DotsAndDashesPage.xaml 檔案會具現化兩Picker
個檢視,一個可讓您選取筆劃上限,第二個用來選取虛線數位:
<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>
中的 dashArrayPicker
前三個專案假設筆劃寬度為10圖元。 { 10, 10 } 陣列適用於虛線,{ 30, 10 } 適用於虛線,而 { 10, 10, 30, 10 } 適用於虛線和虛線。 (其他三項將很快討論。
程式 DotsAndDashesPage
代碼後置檔案包含 PaintSurface
事件處理程式和幾個可存取檢視的 Picker
協助程式例程:
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;
}
在下列螢幕快照中,最左邊的 iOS 畫面會顯示虛線:
不過,Android 畫面也應該使用數位 { 10, 10 } 來顯示虛線,但線條是實心的。 發生什麼事? 問題是Android畫面也有筆劃上限設定 Square
。 這會將所有虛線延伸一半的筆劃寬度,導致它們填滿間距。
若要在使用 或Round
的筆劃上限Square
時解決此問題,您必須將數位中的虛線長度減少筆劃長度(有時導致虛線長度為 0),並增加筆劃長度的間距長度。 這是 XAML 檔案中 Picker
最後三個破折號陣列的計算方式:
- { 10, 10 } 會變成虛線的 { 0, 20 }
- { 30, 10 } 會變成 { 20, 20 } 代表虛線
- { 10, 10, 30, 10 } 會變成 { 0, 20, 20, 20} 代表虛線和虛線
UWP 畫面會顯示的筆劃上限 Round
虛線和虛線。 筆 Round
觸上限通常會以粗線呈現點和虛線的最佳外觀。
到目前為止,尚未提及 方法的第二個參數 SKPathEffect.CreateDash
。 這個參數會命名 phase
為 ,其是指線條開頭的點與虛線圖樣內的位移。 例如,如果虛線陣列是 { 10, 10 } 且 phase
為 10,則線條會以間距而不是點開頭。
參數的 phase
一個有趣的應用程式是在動畫中。 [動畫螺旋] 頁面類似於 Archimedean Spiral 頁面,不同之處在於 類別AnimatedSpiralPage
會使用 Xamarin.FormsDevice.Timer
方法以phase
動畫顯示 參數:
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;
});
}
···
}
當然,您必須實際執行程式,才能看到動畫: