Aracılığıyla paylaş


Satırlar ve Vuruş Uçları

SkiaSharp kullanarak farklı vuruş kapaklarına sahip çizgiler çizmeyi öğrenin

SkiaSharp'ta tek bir çizginin işlenmesi, bir dizi bağlı düz çizginin işlenmesinden çok farklıdır. Ancak, tek çizgiler çizerken bile, çizgilere belirli bir vuruş genişliği vermek genellikle gereklidir. Bu çizgiler genişlediğinde, çizgilerin uçlarının görünümü de önemli hale gelir. Çizginin sonunun görünümüne vuruş üst sınırı denir:

Üç vuruşlu caps seçenekleri

Tek çizgiler çizmek için bağımsız SKCanvas değişkenleri bir nesneyle çizginin başlangıç ve bitiş koordinatlarını gösteren basit DrawLine bir SKPaint yöntem tanımlar:

canvas.DrawLine (x0, y0, x1, y1, paint);

Varsayılan olarak, StrokeWidth yeni örneklenen SKPaint bir nesnenin özelliği 0'dır ve bu, kalınlıkta bir piksellik bir satırı işlemede 1 değeriyle aynı etkiye sahiptir. Bu, telefonlar gibi yüksek çözünürlüklü cihazlarda çok ince görünür, bu nedenle büyük olasılıkla değerini daha büyük bir değere ayarlamak StrokeWidth istersiniz. Ancak, büyük bir kalınlıkta çizgiler çizmeye başladığınızda başka bir sorun daha ortaya çıkar: Bu kalın çizgilerin başlangıç ve bitişleri nasıl işlenmelidir?

Çizgilerin başlangıç ve bitişlerinin görünümü çizgi kapağı veya Skia'da vuruş kapağı olarak adlandırılır. Bu bağlamdaki "cap" sözcüğü, satırın sonunda yer alan bir tür şapkayı ifade eder. nesnesinin StrokeCap SKPaint özelliğini numaralandırmanın aşağıdaki üyelerinden SKStrokeCap birine ayarlarsınız:

  • Butt (varsayılan)
  • Square
  • Round

Bunlar en iyi örnek programla gösterilmiştir. Örnek programın SkiaSharp Çizgileri ve Yolları bölümü, sınıfını temel alan StrokeCapsPage Vuruş Caps başlıklı bir sayfayla başlar. Bu sayfa, numaralandırmanın üç üyesi arasında döngü yaparak hem sabit listesi üyesinin SKStrokeCap adını görüntüleyen hem de bu vuruş üst sınırını kullanarak bir çizgi çizen bir olay işleyicisi tanımlarPaintSurface:

void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
    SKImageInfo info = args.Info;
    SKSurface surface = args.Surface;
    SKCanvas canvas = surface.Canvas;

    canvas.Clear();

    SKPaint textPaint = new SKPaint
    {
        Color = SKColors.Black,
        TextSize = 75,
        TextAlign = SKTextAlign.Center
    };

    SKPaint thickLinePaint = new SKPaint
    {
        Style = SKPaintStyle.Stroke,
        Color = SKColors.Orange,
        StrokeWidth = 50
    };

    SKPaint thinLinePaint = new SKPaint
    {
        Style = SKPaintStyle.Stroke,
        Color = SKColors.Black,
        StrokeWidth = 2
    };

    float xText = info.Width / 2;
    float xLine1 = 100;
    float xLine2 = info.Width - xLine1;
    float y = textPaint.FontSpacing;

    foreach (SKStrokeCap strokeCap in Enum.GetValues(typeof(SKStrokeCap)))
    {
        // Display text
        canvas.DrawText(strokeCap.ToString(), xText, y, textPaint);
        y += textPaint.FontSpacing;

        // Display thick line
        thickLinePaint.StrokeCap = strokeCap;
        canvas.DrawLine(xLine1, y, xLine2, y, thickLinePaint);

        // Display thin line
        canvas.DrawLine(xLine1, y, xLine2, y, thinLinePaint);
        y += 2 * textPaint.FontSpacing;
    }
}

Numaralandırmanın SKStrokeCap her üyesi için işleyici biri 50 piksel vuruş kalınlığına ve diğeri iki piksel vuruş kalınlığıyla üste yerleştirilmiş başka bir çizgi olmak üzere iki çizgi çizer. Bu ikinci çizgi, çizgi kalınlığından ve vuruş başlığından bağımsız olarak çizginin geometrik başlangıcını ve sonunu göstermek için tasarlanmıştır:

Vuruş Caps sayfasının üçlü ekran görüntüsü

Gördüğünüz gibi ve Round vuruş kapakları, Square çizginin uzunluğunu çizginin başında ve sonunda tekrar vuruş genişliğinin yarısı kadar etkili bir şekilde genişletir. İşlenen grafik nesnesinin boyutlarını belirlemek gerektiğinde bu uzantı önemli hale gelir.

sınıfı, SKCanvas biraz tuhaf olan birden çok çizgi çizmek için başka bir yöntem de içerir:

DrawPoints (SKPointMode mode, points, paint)

points parametresi bir değer dizisidir SKPoint ve mode üç üyesi olan numaralandırmanın SKPointMode bir üyesidir:

  • Points tek tek noktaları işlemek için
  • Lines her bir nokta çiftini bağlamak için
  • Polygon ardışık tüm noktaları bağlamak için

Birden Çok Satır sayfasında bu yöntem gösterilir. MultipleLinesPage.xaml dosyası, numaralandırmanın bir üyesini ve numaralandırmanın SKPointMode bir üyesini seçmenize olanak sağlayan iki Picker görünümün örneğini SKStrokeCap oluşturur:

<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.MultipleLinesPage"
             Title="Multiple Lines">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Picker x:Name="pointModePicker"
                Title="Point Mode"
                Grid.Row="0"
                Grid.Column="0"
                SelectedIndexChanged="OnPickerSelectedIndexChanged">
            <Picker.ItemsSource>
                <x:Array Type="{x:Type skia:SKPointMode}">
                    <x:Static Member="skia:SKPointMode.Points" />
                    <x:Static Member="skia:SKPointMode.Lines" />
                    <x:Static Member="skia:SKPointMode.Polygon" />
                </x:Array>
            </Picker.ItemsSource>
            <Picker.SelectedIndex>
                0
            </Picker.SelectedIndex>
        </Picker>

        <Picker x:Name="strokeCapPicker"
                Title="Stroke Cap"
                Grid.Row="0"
                Grid.Column="1"
                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>

        <skiaforms:SKCanvasView x:Name="canvasView"
                                PaintSurface="OnCanvasViewPaintSurface"
                                Grid.Row="1"
                                Grid.Column="0"
                                Grid.ColumnSpan="2" />
    </Grid>
</ContentPage>

ve sabit listelerinin üyelerine başvurmak için ad alanı gerektiğinden SkiaSharp SkiaSharp ad alanı bildirimlerinin SKPointMode SKStrokeCap biraz farklı olduğuna dikkat edin. her iki Picker görünümün SelectedIndexChanged işleyicisi yalnızca nesneyi geçersiz klırSKCanvasView:

void OnPickerSelectedIndexChanged(object sender, EventArgs args)
{
    if (canvasView != null)
    {
        canvasView.InvalidateSurface();
    }
}

XAML dosyasında özelliği Picker 0 olarak ayarlandığında ve örneği başlatılmadan önce SKCanvasView gerçekleştiğinde olay işleyicisi ilk olarak çağrıldığındanSelectedIndex, bu işleyicinin nesnenin varlığını SKCanvasView denetlemesi gerekir.

İşleyici, PaintSurface görünümlerden Picker iki numaralandırma değerini elde eder:

void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
    SKImageInfo info = args.Info;
    SKSurface surface = args.Surface;
    SKCanvas canvas = surface.Canvas;

    canvas.Clear();

    // Create an array of points scattered through the page
    SKPoint[] points = new SKPoint[10];

    for (int i = 0; i < 2; i++)
    {
        float x = (0.1f + 0.8f * i) * info.Width;

        for (int j = 0; j < 5; j++)
        {
            float y = (0.1f + 0.2f * j) * info.Height;
            points[2 * j + i] = new SKPoint(x, y);
        }
    }

    SKPaint paint = new SKPaint
    {
        Style = SKPaintStyle.Stroke,
        Color = SKColors.DarkOrchid,
        StrokeWidth = 50,
        StrokeCap = (SKStrokeCap)strokeCapPicker.SelectedItem
    };

    // Render the points by calling DrawPoints
    SKPointMode pointMode = (SKPointMode)pointModePicker.SelectedItem;
    canvas.DrawPoints(pointMode, points, paint);
}

Ekran görüntüleri çeşitli Picker seçimleri gösterir:

Birden Çok Satır sayfasının üç kez ekran görüntüsü

Soldaki i Telefon, sabit listesi üyesinin SKPointMode.Points satır üst sınırı veya Squareise dizideki SKPoint noktaların her birini kare olarak işlemesine nasıl neden DrawPoints olduğunu Butt gösterir. Satır üst sınırı Roundise daireler işlenir.

Android ekran görüntüsü, sonucunu SKPointMode.Linesgösterir. DrawPoints yöntemi, bu örnekte Roundbelirtilen satır üst sınırını kullanarak her değer çifti SKPoint arasına bir çizgi çizer.

bunun yerine kullandığınızda SKPointMode.Polygon, dizideki ardışık noktalar arasına bir çizgi çizilir, ancak çok yakından bakarsanız, bu çizgilerin bağlı olmadığını görürsünüz. Bu ayrı satırların her biri belirtilen satır üst sınırıyla başlar ve biter. Büyük harflerden birini seçerseniz Round çizgiler bağlı gibi görünebilir, ancak bunlar gerçekten bağlı değildir.

Çizgilerin bağlı olup olmadığı grafik yollarıyla çalışmanın önemli bir yönüdür.