Freigeben über


Die Scherungstransformation

Erfahren Sie, wie die schiefe Transformation gekippte grafische Objekte in SkiaSharp erstellen kann

In SkiaSharp kippt die schiefe Transformation grafische Objekte, z. B. den Schatten in diesem Bild:

Beispiel für das Skewingen aus dem Programm

Die Schiefe wandelt ein Rechteck in ein Parallelogramm um, aber eine schiefe Ellipse ist immer noch eine Ellipse.

Obwohl Xamarin.Forms Eigenschaften für Übersetzung, Skalierung und Drehungen definiert werden, gibt es keine entsprechende Eigenschaft Xamarin.Forms für Neigungen.

Die Skew Methode von SKCanvas akzeptiert zwei Argumente für horizontale Neigung und vertikale Neigung:

public void Skew (Single xSkew, Single ySkew)

Eine zweite Skew Methode kombiniert diese Argumente in einem einzelnen SKPoint Wert:

public void Skew (SKPoint skew)

Es ist jedoch unwahrscheinlich, dass Sie eine dieser beiden Methoden isoliert verwenden.

Auf der Seite "Schiefes Experiment " können Sie mit schiefen Werten experimentieren, die zwischen -10 und 10 liegen. Eine Textzeichenfolge wird in der oberen linken Ecke der Seite positioniert, wobei schiefe Werte aus zwei Slider Elementen abgerufen werden. Dies ist der PaintSurface Handler in der SkewExperimentPage Klasse:

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

    canvas.Clear();

    using (SKPaint textPaint = new SKPaint
    {
        Style = SKPaintStyle.Fill,
        Color = SKColors.Blue,
        TextSize = 200
    })
    {
        string text = "SKEW";
        SKRect textBounds = new SKRect();
        textPaint.MeasureText(text, ref textBounds);

        canvas.Skew((float)xSkewSlider.Value, (float)ySkewSlider.Value);
        canvas.DrawText(text, 0, -textBounds.Top, textPaint);
    }
}

Werte des xSkew Arguments verschieben den unteren Rand des Texts nach rechts für positive Werte oder links für negative Werte. Werte, ySkew die den Text für positive Werte nach unten oder für negative Werte nach unten verschieben:

Dreifacher Screenshot der Seite

Wenn der xSkew Wert das Negative des ySkew Werts ist, ist das Ergebnis drehung, aber auch etwas skaliert.

Die Transformationsformeln sind wie folgt:

x' = x + xSkew · Y

y' = ySkew · x + y

Bei einem positiven xSkew Wert erhöht sich beispielsweise der transformierte x' Wert, wenn y er zunimmt. Das bewirkt die Neigung.

Wenn ein Dreieck 200 Pixel breit und 100 Pixel hoch mit seiner oberen linken Ecke am Punkt (0, 0) positioniert ist und mit einem xSkew Wert von 1,5 gerendert wird, ergeben sich die folgenden Parallelogrammergebnisse:

Der Effekt der Neigungstransformation auf ein Rechteck

Die Koordinaten des unteren Rands haben y Werte von 100, sodass sie um 150 Pixel nach rechts verschoben wird.

Bei Nicht-Null-Werten von xSkew oder ySkew, ist nur der Punkt (0, 0) gleich Standard. Dieser Punkt kann als Das Zentrum der Skewing betrachtet werden. Wenn Sie das Zentrum des Skewings benötigen, um etwas anderes zu sein (was in der Regel der Fall ist), gibt es keine Skew Methode, die dies bereitstellt. Sie müssen Anrufe explizit mit dem Skew Anruf kombinierenTranslate. Führen Sie die folgenden Anrufe aus, um den Skewing zu pxpyzentrieren:

canvas.Translate(px, py);
canvas.Skew(xSkew, ySkew);
canvas.Translate(-px, -py);

Die zusammengesetzten Transformationsformeln sind:

x' = x + xSkew · (y – py)

y' = ySkew · (x – px) + y

Wenn ySkew null ist, wird der px Wert nicht verwendet. Der Wert ist irrelevant und entsprechend für ySkew und py.

Möglicherweise fühlen Sie sich in diesem Diagramm mit der Angabe von Schiefe als Winkel der Neigung vertrauter, z. B. der Winkel α:

Die Auswirkung der Neigungstransformation auf ein Rechteck mit einem schrägen Winkel, der angegeben ist

Das Verhältnis der 150-Pixel-Schicht zur vertikalen 100 Pixel ist der Tangens dieses Winkels, in diesem Beispiel 56,3 Grad.

Die XAML-Datei der Seite "Skew Angle Experiment " ähnelt der Seite "Schiefer Winkel ", mit der Ausnahme, dass die Slider Elemente von -90 Grad bis 90 Grad reichen. Die SkewAngleExperiment CodeBehind-Datei zentrieren den Text auf der Seite und wird verwendet Translate , um eine Mitte der Seite zu setzen. Eine kurze SkewDegrees Methode unten im Code konvertiert Winkel in schiefe Werte:

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

    canvas.Clear();

    using (SKPaint textPaint = new SKPaint
    {
        Style = SKPaintStyle.Fill,
        Color = SKColors.Blue,
        TextSize = 200
    })
    {
        float xCenter = info.Width / 2;
        float yCenter = info.Height / 2;

        string text = "SKEW";
        SKRect textBounds = new SKRect();
        textPaint.MeasureText(text, ref textBounds);
        float xText = xCenter - textBounds.MidX;
        float yText = yCenter - textBounds.MidY;

        canvas.Translate(xCenter, yCenter);
        SkewDegrees(canvas, xSkewSlider.Value, ySkewSlider.Value);
        canvas.Translate(-xCenter, -yCenter);
        canvas.DrawText(text, xText, yText, textPaint);
    }
}

void SkewDegrees(SKCanvas canvas, double xDegrees, double yDegrees)
{
    canvas.Skew((float)Math.Tan(Math.PI * xDegrees / 180),
                (float)Math.Tan(Math.PI * yDegrees / 180));
}

Als Winkel nähert sich positive oder negative 90 Grad, nähert sich der Tangens unendlich, aber Winkel bis zu ca. 80 Grad sind verwendbar:

Dreifacher Screenshot der Seite

Eine kleine negative horizontale Schiefe kann schrägen oder kursiv formatierten Text nachahmen, wie die Seite "Schräger Text " veranschaulicht. Die ObliqueTextPage Klasse zeigt, wie dies geschieht:

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

    canvas.Clear();

    using (SKPaint textPaint = new SKPaint()
    {
        Style = SKPaintStyle.Fill,
        Color = SKColors.Maroon,
        TextAlign = SKTextAlign.Center,
        TextSize = info.Width / 8       // empirically determined
    })
    {
        canvas.Translate(info.Width / 2, info.Height / 2);
        SkewDegrees(canvas, -20, 0);
        canvas.DrawText(Title, 0, 0, textPaint);
    }
}

void SkewDegrees(SKCanvas canvas, double xDegrees, double yDegrees)
{
    canvas.Skew((float)Math.Tan(Math.PI * xDegrees / 180),
                (float)Math.Tan(Math.PI * yDegrees / 180));
}

Die TextAlign Eigenschaft von SKPaint ist auf Center. Ohne Transformationen positioniert der DrawText Aufruf mit Koordinaten von (0, 0) den Text mit der horizontalen Mitte des Basisplans in der oberen linken Ecke. Der SkewDegrees Text wird horizontal um 20 Grad relativ zur Basislinie schief. Der Translate Aufruf verschiebt die horizontale Mitte der Textbasislinie in die Mitte des Zeichenbereichs:

Dreifacher Screenshot der Seite

Auf der Seite "Schiefer Schattentext " wird veranschaulicht, wie Sie eine Kombination aus einer 45-Grad-Schiefe und einer vertikalen Skalierung verwenden, um einen Textschatten zu erstellen, der sich vom Text abneigungen lässt. Dies ist der relevante Teil des PaintSurface Handlers:

using (SKPaint textPaint = new SKPaint())
{
    textPaint.Style = SKPaintStyle.Fill;
    textPaint.TextSize = info.Width / 6;   // empirically determined

    // Common to shadow and text
    string text = "Shadow";
    float xText = 20;
    float yText = info.Height / 2;

    // Shadow
    textPaint.Color = SKColors.LightGray;
    canvas.Save();
    canvas.Translate(xText, yText);
    canvas.Skew((float)Math.Tan(-Math.PI / 4), 0);
    canvas.Scale(1, 3);
    canvas.Translate(-xText, -yText);
    canvas.DrawText(text, xText, yText, textPaint);
    canvas.Restore();

    // Text
    textPaint.Color = SKColors.Blue;
    canvas.DrawText(text, xText, yText, textPaint);
}

Der Schatten wird zuerst und dann der Text angezeigt:

Dreifacher Screenshot der Seite

Die an die DrawText Methode übergebene vertikale Koordinate gibt die Position des Texts relativ zum Basisplan an. Dies ist die gleiche vertikale Koordinate, die für die Mitte der Skewing verwendet wird. Dieses Verfahren funktioniert nicht, wenn die Textzeichenfolge absteigende Elemente enthält. Ersetzen Sie z. B. das Wort "skurrig" für "Schatten", und hier sehen Sie das Ergebnis:

Dreifacher Screenshot der Seite

Der Schatten und der Text werden weiterhin an der Basislinie ausgerichtet, aber der Effekt sieht einfach falsch aus. Um dies zu beheben, müssen Sie die Textgrenzen abrufen:

SKRect textBounds = new SKRect();
textPaint.MeasureText(text, ref textBounds);

Die Translate Aufrufe müssen an die Höhe der Absteigenden angepasst werden:

canvas.Translate(xText, yText + textBounds.Bottom);
canvas.Skew((float)Math.Tan(-Math.PI / 4), 0);
canvas.Scale(1, 3);
canvas.Translate(-xText, -yText - textBounds.Bottom);

Nun erstreckt sich der Schatten vom Unteren dieser Absteigenden:

Dreifacher Screenshot der Seite