SkiaSharp'ta Noktalar ve Tireler
SkiaSharp'ta noktalı ve kesikli çizgiler çizmenin inceliklerinde ustalaşın
SkiaSharp, düz olmayan ama bunun yerine noktalardan ve kısa çizgilerden oluşan çizgiler çizmenizi sağlar:
Bunu, özelliğine ayarladığınız sınıfın SKPathEffect
bir örneği olan yol efektiyle SKPaint
yaparsınız.PathEffect
tarafından SKPathEffect
tanımlanan statik oluşturma yöntemlerinden birini kullanarak bir yol efekti oluşturabilir (veya yol efektlerini birleştirebilirsiniz). (SKPathEffect
SkiaSharp tarafından desteklenen altı efektden biridir; diğerleri SkiaSharp Etkisi bölümünde açıklanmıştır.)
Noktalı veya kesikli çizgiler çizmek için statik yöntemini kullanırsınız SKPathEffect.CreateDash
. İki bağımsız değişken vardır: Bu ilk olarak nokta ve tirelerin uzunluklarını ve aralarındaki boşlukların uzunluğunu gösteren bir değer dizisidir float
. Bu dizi çift sayıda öğeye sahip olmalı ve en az iki öğe olmalıdır. (Dizide sıfır öğe olabilir, ancak bu da düz bir çizgiyle sonuçlanabilir.) İki öğe varsa, birincisi noktanın veya tirenin uzunluğu, ikincisi de bir sonraki nokta veya tireden önceki boşluğun uzunluğudur. İkiden fazla öğe varsa, bunlar şu sıradadır: tire uzunluğu, boşluk uzunluğu, tire uzunluğu, boşluk uzunluğu vb.
Genel olarak, tire ve boşluk uzunluklarını vuruş genişliğinin bir katı yapmak istersiniz. Örneğin, vuruş genişliği 10 pikselse, { 10, 10 } dizisi noktalı bir çizgi çizer ve nokta ve boşluklar vuruş kalınlığıyla aynı uzunlukta olur.
Ancak, StrokeCap
nesnenin SKPaint
ayarı bu noktaları ve kısa çizgileri de etkiler. Kısa süre sonra göreceğiniz gibi bu, bu dizinin öğeleri üzerinde bir etkiye sahiptir.
Noktalı ve kesikli çizgiler, Noktalar ve Tireler sayfasında gösterilir. DotsAndDashesPage.xaml dosyası iki görünümün örneğini Picker
oluşturur. Bunlardan biri bir vuruş üst sınırı seçmenize, ikincisi ise tire dizisini seçmenize izin verir:
<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>
içindeki ilk üç öğe, dashArrayPicker
vuruş genişliğinin 10 piksel olduğunu varsayar. { 10, 10 } dizisi noktalı çizgi içindir, { 30, 10 } kesikli çizgi içindir ve { 10, 10, 30, 10 } noktalı çizgi içindir. (Diğer üçü kısa süre sonra ele alınacaktır.)
Arka DotsAndDashesPage
plandaki kod dosyası, olay işleyicisini PaintSurface
ve görünümlere erişmek Picker
için birkaç yardımcı yordam içerir:
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;
}
Aşağıdaki ekran görüntülerinde, en soldaki iOS ekranında noktalı bir çizgi gösterilir:
Ancak Android ekranının ayrıca { 10, 10 } dizisini kullanarak noktalı bir çizgi göstermesi gerekir, ancak bunun yerine çizgi düzdür. Neler oldu? Sorun, Android ekranında da bir vuruş üst sınırı ayarı olmasıdır Square
. Bu, tüm tireleri vuruş genişliğinin yarısı kadar genişletir ve boşlukları doldurmalarına neden olur.
veya Round
vuruş üst sınırı Square
kullanırken bu sorunu çözmek için dizideki tire uzunluklarını vuruş uzunluğuna göre azaltmanız (bazen tire uzunluğu 0'a neden olur) ve aralık uzunluklarını vuruş uzunluğuna göre artırmanız gerekir. XAML dosyasındaki Picker
son üç tire dizisi bu şekilde hesaplandı:
- { 10, 10 } noktalı çizgi için { 0, 20 } olur
- { 30, 10 } kesikli çizgi için { 20, 20 } olur
- { 10, 10, 30, 10 } noktalı ve kesikli çizgi için { 0, 20, 20, 20} olur
UWP ekranında, vuruş üst sınırı Round
için noktalı ve kesikli çizgi gösterilir. Vuruş Round
başlığı genellikle kalın çizgilerde en iyi nokta ve çizgi görünümünü verir.
Şu ana kadar yöntemin ikinci parametresinden SKPathEffect.CreateDash
bahsedilmemiştir. Bu parametre adlandırılır phase
ve çizginin başlangıcı için nokta ve tire deseni içindeki bir uzaklığı ifade eder. Örneğin, tire dizisi { 10, 10 } ve phase
10 ise, çizgi nokta yerine boşlukla başlar.
Parametresinin phase
ilginç bir uygulaması animasyondur. Animasyonlu Spiral sayfası Archimedean Spiral sayfasına benzer, ancak AnimatedSpiralPage
sınıfı parametresine phase
Xamarin.FormsDevice.Timer
yöntemini kullanarak animasyon uygular:
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;
});
}
···
}
Elbette, animasyonu görmek için programı çalıştırmanız gerekir: