SkiaSharp의 점과 대시
SkiaSharp에서 점선과 파선 그리기의 복잡성 마스터
SkiaSharp를 사용하면 단색이 아니라 점과 대시로 구성된 선을 그릴 수 있습니다.
경로 효과를 사용하여 이 작업을 수행합니다. 이 작업은 속성으로 PathEffect
설정한 클래스의 SKPathEffect
SKPaint
인스턴스입니다. 에 정의된 SKPathEffect
정적 생성 방법 중 하나를 사용하여 경로 효과를 만들거나 경로 효과를 결합할 수 있습니다. (SKPathEffect
SkiaSharp에서 지원하는 여섯 가지 효과 중 하나이며, 다른 효과는 SkiaSharp 효과 섹션에 설명되어 있습니다.)
점선 또는 파선선을 그리려면 정적 메서드를 SKPathEffect.CreateDash
사용합니다. 두 인수가 있습니다. 첫 번째는 점과 대시의 float
길이와 그 사이의 공백 길이를 나타내는 값 배열입니다. 이 배열에는 짝수의 요소가 있어야 하며 두 개 이상의 요소가 있어야 합니다. (배열에는 요소가 0일 수 있지만 실선이 생성됩니다.) 두 개의 요소가 있는 경우 첫 번째는 점 또는 대시의 길이이고, 두 번째는 다음 점 또는 대시 앞의 간격 길이입니다. 두 개 이상의 요소가 있는 경우 대시 길이, 간격 길이, 대시 길이, 간격 길이 등 순서대로 표시됩니다.
일반적으로 대시와 간격 길이를 스트로크 너비의 배수로 만들려고 합니다. 예를 들어 스트로크 너비가 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
이벤트 처리기와 보기에 액세스하기 위한 몇 가지 도우미 루틴이 Picker
포함되어 PaintSurface
있습니다.
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
도 있다는 것입니다. 이렇게 하면 모든 대시가 스트로크 너비의 절반으로 확장되어 간격을 채웁니다.
또는 스트로크 캡을 사용할 때 이 문제를 해결하려면 배열의 Square
Round
대시 길이를 스트로크 길이로 줄이고(때로는 대시 길이가 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
흥미로운 응용 프로그램 중 하나는 애니메이션에 있습니다. 애니메이션 나선형 페이지는 클래스가 메서드를 사용하여 Xamarin.FormsDevice.Timer
매개 변수에 애니메이션 효과를 주는 것을 AnimatedSpiralPage
제외하고 Archimedean 나선형 페이지와 유사합니다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;
});
}
···
}
물론 애니메이션을 보려면 프로그램을 실제로 실행해야 합니다.