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:
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:
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:
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 px
py
zentrieren:
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 α:
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:
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:
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:
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:
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: