Freigeben über


Pfadgrundlagen in SkiaSharp

Erkunden Des SkiaSharp SKPath-Objekts zum Kombinieren verbundener Linien und Kurven

Eines der wichtigsten Features des Grafikpfads ist die Möglichkeit, zu definieren, wann mehrere Linien verbunden werden sollen und wann sie nicht verbunden werden sollen. Der Unterschied kann signifikant sein, da die Oberen dieser beiden Dreiecke zeigen:

Zwei Dreiecke mit dem Unterschied zwischen verbundenen und getrennten Linien

Ein Grafikpfad wird vom SKPath Objekt gekapselt. Ein Pfad ist eine Sammlung mit einer oder mehreren Konturen. Jede Kontur ist eine Sammlung verbundener gerader Linien und Kurven. Konturen sind nicht miteinander verbunden, aber sie können sich visuell überschneiden. Eine einzelne Kontur kann sich manchmal auch selber überlappen.

Eine Kontur beginnt in der Regel mit einem Aufruf der folgenden Methode von SKPath:

  • MoveTo um eine neue Kontur zu beginnen

Das Argument für diese Methode ist ein einzelner Punkt, den Sie entweder als SKPoint Wert oder als separate X- und Y-Koordinaten ausdrücken können. Der MoveTo Aufruf richtet einen Punkt am Anfang der Kontur und einen ersten aktuellen Punkt ein. Sie können die folgenden Methoden aufrufen, um die Kontur mit einer Linie oder Kurve vom aktuellen Punkt zu einem in der Methode angegebenen Punkt fortzusetzen, der dann zum neuen aktuellen Punkt wird:

  • LineTo um dem Pfad eine gerade Linie hinzuzufügen
  • ArcTo um einen Bogen hinzuzufügen, bei dem es sich um eine Linie im Umfang eines Kreises oder einer Ellipse handelt
  • CubicTo so fügen Sie eine kubische Bézier-Spline hinzu
  • QuadTo so fügen Sie eine quadratische Bézier-Spline hinzu
  • ConicTo um eine rationale quadratische Bezier-Spline hinzuzufügen, die konische Abschnitte genau rendern kann (Auslassungspunkte, Parabolien und Hyperbolas)

Keiner dieser fünf Methoden enthält alle Informationen, die zum Beschreiben der Linie oder Kurve erforderlich sind. Jede dieser fünf Methoden funktioniert in Verbindung mit dem aktuellen Punkt, der durch den Methodenaufruf unmittelbar vorausgeht. Beispielsweise fügt die LineTo Methode der Kontur basierend auf dem aktuellen Punkt eine gerade Linie hinzu, sodass der Parameter LineTo nur ein einzelner Punkt ist.

Die SKPath Klasse definiert auch Methoden, die die gleichen Namen wie diese sechs Methoden haben, aber mit einem R am Anfang:

Das R steht für relativ. Diese Methoden haben dieselbe Syntax wie die entsprechenden Methoden ohne die R , sind aber relativ zum aktuellen Punkt. Dies ist praktisch, um ähnliche Teile eines Pfads in einer Methode zu zeichnen, die Sie mehrmals aufrufen.

Eine Kontur endet mit einem anderen Aufruf MoveTo oder RMoveTo, der eine neue Kontur beginnt, oder mit einem Aufruf, Closeder die Kontur schließt. Die Close Methode fügt automatisch eine gerade Linie vom aktuellen Punkt an den ersten Punkt der Kontur an und markiert den Pfad als geschlossen, was bedeutet, dass er ohne Strichkappen gerendert wird.

Der Unterschied zwischen offenen und geschlossenen Konturen wird auf der Seite "Zwei Dreieckskonturen " veranschaulicht, die ein SKPath Objekt mit zwei Konturen verwendet, um zwei Dreiecke zu rendern. Die erste Kontur ist geöffnet und die zweite ist geschlossen. Dies ist die TwoTriangleContoursPage-Klasse:

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

    canvas.Clear();

    // Create the path
    SKPath path = new SKPath();

    // Define the first contour
    path.MoveTo(0.5f * info.Width, 0.1f * info.Height);
    path.LineTo(0.2f * info.Width, 0.4f * info.Height);
    path.LineTo(0.8f * info.Width, 0.4f * info.Height);
    path.LineTo(0.5f * info.Width, 0.1f * info.Height);

    // Define the second contour
    path.MoveTo(0.5f * info.Width, 0.6f * info.Height);
    path.LineTo(0.2f * info.Width, 0.9f * info.Height);
    path.LineTo(0.8f * info.Width, 0.9f * info.Height);
    path.Close();

    // Create two SKPaint objects
    SKPaint strokePaint = new SKPaint
    {
        Style = SKPaintStyle.Stroke,
        Color = SKColors.Magenta,
        StrokeWidth = 50
    };

    SKPaint fillPaint = new SKPaint
    {
        Style = SKPaintStyle.Fill,
        Color = SKColors.Cyan
    };

    // Fill and stroke the path
    canvas.DrawPath(path, fillPaint);
    canvas.DrawPath(path, strokePaint);
}

Die erste Kontur besteht aus einem Aufruf zur MoveTo Verwendung von X- und Y-Koordinaten anstelle eines SKPoint Werts, gefolgt von drei Aufrufen zum LineTo Zeichnen der drei Seiten des Dreiecks. Die zweite Kontur hat nur zwei Aufrufe, LineTo aber sie beendet die Kontur mit einem Aufruf Close, der die Kontur schließt. Der Unterschied ist signifikant:

Dreifacher Screenshot der Seite

Wie Sie sehen können, ist die erste Kontur offensichtlich eine Reihe von drei verbundenen Linien, aber das Ende verbindet sich nicht mit dem Anfang. Die beiden Linien überlappen sich oben. Die zweite Kontur ist offensichtlich geschlossen und wurde mit weniger LineTo Aufrufen erreicht, da die Close Methode automatisch eine letzte Linie zum Schließen der Kontur hinzufügt.

SKCanvas definiert nur eine DrawPath Methode, die in dieser Demonstration zweimal aufgerufen wird, um den Pfad auszufüllen und zu strichen. Alle Konturen sind gefüllt, auch diejenigen, die nicht geschlossen sind. Für das Ausfüllen von ungeraden Pfaden wird davon ausgegangen, dass eine gerade Linie zwischen den Anfangs- und Endpunkten der Konturen vorhanden ist. Wenn Sie den letzten LineTo aus der ersten Kontur entfernen oder den Close Aufruf aus der zweiten Kontur entfernen, hat jede Kontur nur zwei Seiten, wird aber gefüllt, als wäre es ein Dreieck.

SKPath definiert viele andere Methoden und Eigenschaften. Die folgenden Methoden fügen dem Pfad ganze Konturen hinzu, die je nach Methode geschlossen oder nicht geschlossen werden können:

Beachten Sie, dass ein SKPath Objekt nur eine Geometrie definiert – eine Reihe von Punkten und Verbindungen. Nur wenn ein SKPath Objekt mit einem SKPaint Objekt kombiniert wird, wird der Pfad mit einer bestimmten Farbe, Strichbreite usw. gerendert. Denken Sie auch daran, dass das SKPaint an die DrawPath Methode übergebene Objekt Merkmale des gesamten Pfads definiert. Wenn Sie etwas zeichnen möchten, das mehrere Farben erfordert, müssen Sie für jede Farbe einen separaten Pfad verwenden.

Genau wie die Darstellung des Anfangs- und Endes einer Linie durch eine Strichkappe definiert wird, wird die Darstellung der Verbindung zwischen zwei Linien durch eine Strichverknappung definiert. Sie geben dies an, indem Sie die StrokeJoin Eigenschaft eines SKPaint Elements der SKStrokeJoin Enumeration festlegen:

  • Miter für eine pointy Join
  • Round für einen abgerundeten Beitritt
  • Bevel für eine abgehackte Verknüpfung

Auf der Seite "Strichverknappungen " werden diese drei Strichverknappungen mit Code angezeigt, der der Seite " Strichbuchstaben " ähnelt. Dies ist der PaintSurface Ereignishandler in der StrokeJoinsPage Klasse:

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.Right
    };

    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 - 100;
    float xLine1 = 100;
    float xLine2 = info.Width - xLine1;
    float y = 2 * textPaint.FontSpacing;
    string[] strStrokeJoins = { "Miter", "Round", "Bevel" };

    foreach (string strStrokeJoin in strStrokeJoins)
    {
        // Display text
        canvas.DrawText(strStrokeJoin, xText, y, textPaint);

        // Get stroke-join value
        SKStrokeJoin strokeJoin;
        Enum.TryParse(strStrokeJoin, out strokeJoin);

        // Create path
        SKPath path = new SKPath();
        path.MoveTo(xLine1, y - 80);
        path.LineTo(xLine1, y + 80);
        path.LineTo(xLine2, y + 80);

        // Display thick line
        thickLinePaint.StrokeJoin = strokeJoin;
        canvas.DrawPath(path, thickLinePaint);

        // Display thin line
        canvas.DrawPath(path, thinLinePaint);
        y += 3 * textPaint.FontSpacing;
    }
}

Dies ist das Programm, das ausgeführt wird:

Dreifacher Screenshot der Seite

Die Miter-Verknüpfung besteht aus einem scharfen Punkt, an dem sich die Linien verbinden. Wenn sich zwei Linien in einem kleinen Winkel verbinden, kann die Miter-Verknüpfung ziemlich lang werden. Um übermäßig lange Miter-Verknüpfungen zu verhindern, wird die Länge der Miter-Verknüpfung durch den Wert der StrokeMiter Eigenschaft von SKPaintbegrenzt. Eine Miter-Verknüpfung, die diese Länge überschreitet, wird abgehackt, um zu einer Abgeschrägungsbeitritt zu werden.