기울이기 변환The Skew Transform

샘플 다운로드 샘플 다운로드Download Sample Download the sample

기울이기 변환에서 SkiaSharp 기운된 그래픽 개체를 만들 수 있습니다 하는 방법을 참조 하세요.See how the skew transform can create tilted graphical objects in SkiaSharp

SkiaSharp, 기울이기 변환 그림자가 그림과에서 같은 그래픽 개체를 기울이는:In SkiaSharp, the skew transform tilts graphical objects, such as the shadow in this image:

오차는 평행 사변형에 사각형을 설정 하지만 불균형된 타원은 타원 계속 합니다.The skew turns a rectangle into a parallelogram, but a skewed ellipse is still an ellipse.

Xamarin.Forms 변환, 배율 및 회전에 대 한 속성을 정의 하지만 해당 속성이 없는 Xamarin.Forms의 오차에 대 한 합니다.Although Xamarin.Forms defines properties for translation, scaling, and rotations, there is no corresponding property in Xamarin.Forms for skew.

합니다 Skew 메서드의 SKCanvas 기울이기 세로 및 가로 기울이기를 대 한 두 개의 인수를 허용 합니다.The Skew method of SKCanvas accepts two arguments for horizontal skew and vertical skew:

public void Skew (Single xSkew, Single ySkew)

두 번째 Skew 메서드는 이러한 인수는 단일에서 결합 SKPoint 값:A second Skew method combines those arguments in a single SKPoint value:

public void Skew (SKPoint skew)

그러나 그럴 가능성은 사용할 두 가지 방법 중 하나에서 격리 합니다.However, it's unlikely that you'll be using either of these two methods in isolation.

합니다 실험 기울이기 오차를 사용 하 여 실험 페이지 있습니다 – 10에서 10 사이의 사이의 값입니다.The Skew Experiment page lets you experiment with skew values that range between –10 and 10. 텍스트 문자열에서 두 가져온 오차 값을 사용 하 여 페이지의 왼쪽 위 모퉁이에 배치 됩니다 Slider 요소입니다.A text string is positioned in the upper-left corner of the page, with skew values obtained from two Slider elements. 다음은 PaintSurface 처리기에는 SkewExperimentPage 클래스:Here is the PaintSurface handler in the SkewExperimentPage class:

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);
    }
}

값을 xSkew 양수 값에 대 한 오른쪽 텍스트 또는 음수 값에 대 한 왼쪽의 아래쪽을 이동 하는 인수입니다.Values of the xSkew argument shift the bottom of the text right for positive values or left for negative values. ySkew 양수 또는 음수 값에 대해 텍스트의 오른쪽 이동 합니다.Values of ySkew shift the right of the text down for positive values or up for negative values:

경우는 xSkew 값은 음수를 ySkew 값 결과 회전 이지만으로 다소 비율도 UWP 표시를 나타냅니다.If the xSkew value is the negative of the ySkew value, the result is rotation, but also scaled somewhat as the UWP display indicates.

변환 수식에는 다음과 같습니다.The transform formulas are as follows:

x' = x + xSkew? yx' = x + xSkew · y

y' ySkew? = x + yy' = ySkew · x + y

양수에 대 한 예를 들어 xSkew 값을 변환 된 x' 값으로 증가 y 증가 합니다.For example, for a positive xSkew value, the transformed x' value increases as y increases. 기울기 원인입니다.That's what causes the tilt.

왼쪽 위 모퉁이가 점 (0, 0)를 배치 하는 사용 하 여 렌더링 되는 삼각형 200 픽셀 너비 고 100 픽셀 짜리는 xSkew 값이 1.5, 다음 평행 사변형 결과:If a triangle 200 pixels wide and 100 pixels high is positioned with its upper-left corner at the point (0, 0) and is rendered with an xSkew value of 1.5, the following parallelogram results:

아래쪽 가장자리의 좌표의 y 값이 100 인 이므로 150 픽셀을 오른쪽으로 옮겨집니다.The coordinates of the bottom edge have y values of 100, so it is shifted 150 pixels to the right.

값이 0이 아닌 xSkew 또는 ySkew를 점 (0, 0) 동일 하 게 유지 합니다.For non-zero values of xSkew or ySkew, only the point (0, 0) remains the same. 이때 기울이기 원의 간주할 수 있습니다.That point can be considered the center of skewing. 그 밖의 내용은 되도록 기울이기의 가운데 (이 일반적으로 대/소문자)을 해야 하는 경우 없습니다 Skew 메서드를 제공 하는 합니다.If you need the center of skewing to be something else (which is usually the case), there is no Skew method that provides that. 명시적으로 결합 해야 Translate 사용 하 여 호출 된 Skew 호출 합니다.You'll need to explicitly combine Translate calls with the Skew call. 가운데에서 기울이기 pxpy, 다음 호출을 수행 합니다.To center the skewing at px and py, make the following calls:

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

복합 변환 수식은 다음과 같습니다.The composite transform formulas are:

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

y' ySkew? = (x-px) + yy' = ySkew · (x – px) + y

하는 경우 ySkew 가 0 이면 해당 px 값은 사용 되지 않습니다.If ySkew is zero, then the px value is not used. 값을 관련 되지 않습니다 및 마찬가지로 ySkewpy입니다.The value is irrelevant, and similarly for ySkew and py.

수 편하다면 기울기 각도 α가 다이어그램과에서 같은 기울기 각도를 지정 합니다.You might feel more comfortable specifying skew as an angle of tilt, such as the angle α in this diagram:

100 픽셀 세로 150 픽셀 shift의 비율은이 예에서 해당 각도의 탄젠트 56.3 (도).The ratio of the 150-pixel shift to the 100-pixel vertical is the tangent of that angle, in this example 56.3 degrees.

XAML 파일을를 각도 실험 기울이기 비슷합니다는 기울이기 각도 는 제외 하 고 페이지를 Slider 요소 인에서 90도 사이입니다.The XAML file of the Skew Angle Experiment page is similar to the Skew Angle page except that the Slider elements range from –90 degrees to 90 degrees. SkewAngleExperiment 코드 숨김 파일 페이지에서 텍스트를 가운데 정렬 하 고 사용 하 여 Translate 기울이기 페이지의 가운데를 중심을 설정 합니다.The SkewAngleExperiment code-behind file centers the text on the page and uses Translate to set a center of skewing to the center of the page. 짧은 SkewDegrees 메서드 코드의 맨 아래에서 각도 값 기울이기 변환 합니다.A short SkewDegrees method at the bottom of the code converts angles to skew values:

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));
}

각도 양수 또는 음수 90도 다가오면 탄젠트 가까워지면 무한대 있지만 약 80도 정도까지 각도 사용할 수 없습니다.As an angle approaches positive or negative 90 degrees, the tangent approaches infinity, but angles up to about 80 degrees or so are usable:

작은 음수 가로 기울이기를으로 오블리크 또는 기울임꼴 텍스트를 모방 합니다 오블리크 텍스트 페이지를 보여 줍니다.A small negative horizontal skew can mimic oblique or italic text, as the Oblique Text page demonstrates. 합니다 ObliqueTextPage 클래스가 어떻게 수행 되는지 보여 줍니다.The ObliqueTextPage class shows how it's done:

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));
}

합니다 TextAlign 속성을 SKPaint 로 설정 된 Center합니다.The TextAlign property of SKPaint is set to Center. 모든 변환 없이 DrawText 의 좌표를 사용 하 여 호출 (0, 0) 왼쪽 위 모퉁이에서 기준의 가로 가운데를 사용 하 여 텍스트의 위치는입니다.Without any transforms, the DrawText call with coordinates of (0, 0) would position the text with the horizontal center of the baseline at the upper-left corner. SkewDegrees 기준선을 기준으로 20도 텍스트를 가로로 기울어집니다.The SkewDegrees skews the text horizontally 20 degrees relative to the baseline. Translate 호출 캔버스의 가운데에 텍스트의 기준선의 가로 가운데를 이동 합니다.The Translate call moves the horizontal center of the text's baseline to the center of the canvas:

합니다 그림자 텍스트 기울이기 페이지 텍스트에서 기울이는 텍스트 그림자 45도 기울이기 및 세로 눈금을 조합해 서 사용 하는 방법에 설명 합니다.The Skew Shadow Text page demonstrates how to use a combination of a 45-degree skew and vertical scale to make a text shadow that tilts away from the text. 관련 부분은 여기는 PaintSurface 처리기:Here's the pertinent part of the PaintSurface handler:

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);
}

그림자가 표시 된 첫 번째 및 다음 텍스트:The shadow is displayed first and then the text:

에 전달 하는 세로 좌표는 DrawText 메서드 기준선을 기준으로 텍스트의 위치를 나타냅니다.The vertical coordinate passed to the DrawText method indicates the position of the text relative to the baseline. 기울이기의 중심에 사용 되는 동일한 세로 좌표입니다.That is the same vertical coordinate used for the center of skewing. 텍스트 문자열 디센더를 포함 하는 경우에이 기술은 작동 하지 않습니다.This technique will not work if the text string contains descenders. 예를 들어, "섀도"에 대 한 "마구" 라는 단어를 대체 하 고 결과 다음과 같습니다.For example, substitute the word "quirky" for "Shadow" and here's the result:

섀도 및 텍스트는 기준선에 맞춘 여전히 있지만 효과 깔 잘못 된 합니다.The shadow and text are still aligned at the baseline, but the effect just looks wrong. 이 문제를 해결 하려면 텍스트 범위를 가져오려고 합니다.To fix it, you need to obtain the text bounds:

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

Translate 호출 디센더의 높이로 조정 해야 합니다.The Translate calls need to be adjusted by the height of the descenders:

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);

이제 이러한 디센더와 맨 아래에서 그림자를 확장합니다.Now the shadow extends from the bottom of those descenders: