Udostępnij za pośrednictwem


Pochylenie — przekształcenie

Zobacz, jak transformacja niesymetryczności może tworzyć przechylone obiekty graficzne w skiaSharp

W skiaSharp przekształć przekształć przechyla obiekty graficzne, takie jak cień na poniższej ilustracji:

Przykład niesymetryczności z programu Niesymetryczny tekst w tle

Niesymetryczność zamienia prostokąt w równoległyogram, ale niesymetryczny wielokropek jest nadal wielokropkiem.

Mimo że Xamarin.Forms definiuje właściwości tłumaczenia, skalowania i rotacji, nie ma odpowiedniej właściwości dla Xamarin.Forms niesymetryczności.

Metoda Skew akceptowania SKCanvas dwóch argumentów dla niesymetryczności poziomej i niesymetryczności pionowej:

public void Skew (Single xSkew, Single ySkew)

Druga Skew metoda łączy te argumenty w jednej SKPoint wartości:

public void Skew (SKPoint skew)

Jest jednak mało prawdopodobne, że będziesz używać jednej z tych dwóch metod w izolacji.

Strona Niesymetryczność eksperymentu umożliwia eksperymentowanie z niesymetrycznymi wartościami z zakresu od –10 do 10. Ciąg tekstowy jest umieszczony w lewym górnym rogu strony z niesymetrycznymi wartościami uzyskanymi z dwóch Slider elementów. PaintSurface Oto procedura obsługi w SkewExperimentPage klasie:

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 Wartości argumentu przesuwają dolną część tekstu w prawo dla wartości dodatnich lub pozostawione dla wartości ujemnych. ySkew Wartości przesunięcia po prawej stronie tekstu w dół dla wartości dodatnich lub w górę dla wartości ujemnych:

Zrzut ekranu przedstawiający stronę Niesymetryczne eksperymenty

xSkew Jeśli wartość jest ujemna ySkew wartości, wynik jest obracany, ale również nieco skalowany.

Formuły przekształcania są następujące:

x' = x + xSkew · Y

y' = ySkew · x + y

Na przykład w przypadku wartości dodatniej xSkew przekształcona x' wartość zwiększa się wraz ze y wzrostem. To właśnie powoduje pochylenie.

Jeśli trójkąt o szerokości 200 pikseli i wysokości 100 pikseli jest umieszczony w lewym górnym rogu w punkcie (0, 0) i jest renderowany z wartością xSkew 1,5, następujące wyniki równoległości:

Wpływ przekształcenia niesymetrycznego na prostokąt

Współrzędne dolnej krawędzi mają y wartości 100, więc jest przesunięty 150 pikseli po prawej stronie.

W przypadku wartości xSkew innych niż zero lub ySkewtylko punkt (0, 0) pozostaje taki sam. Ten punkt można uznać za środek niesymetryczności. Jeśli potrzebujesz środka niesymetryczności, aby być czymś innym (zwykle jest to przypadek), nie Skew ma metody, która to zapewnia. Należy jawnie połączyć Translate wywołania z wywołaniem Skew . Aby wyśrodkować niesymetryczność na px i py, wykonaj następujące wywołania:

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

Formuły transformacji złożonej to:

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

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

Jeśli ySkew wartość jest równa zero, px wartość nie jest używana. Wartość jest nieistotna i podobnie dla ySkew i py.

Możesz czuć się bardziej komfortowo, określając niesymetryczność jako kąt pochylenia, taki jak kąt α na tym diagramie:

Wpływ przekształcenia niesymetrycznego na prostokąt ze wskazanym kątem niesymetryczności

Współczynnik przesunięcia 150 pikseli do 100 pikseli w pionie jest tangensem tego kąta, w tym przykładzie 56,3 stopni.

Plik XAML strony Niesymetryczny eksperyment kątowy jest podobny do strony Kąt niesymetryczny, z tą różnicą, że Slider elementy wahają się od –90 stopni do 90 stopni. Plik SkewAngleExperiment związany z kodem koncentruje tekst na stronie i używa Translate go do ustawienia środka niesymetryczności do środka strony. Krótka SkewDegrees metoda w dolnej części kodu konwertuje kąty na niesymetryczne wartości:

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

Gdy kąt zbliża się do dodatnich lub ujemnych 90 stopni, tangens zbliża się do nieskończoności, ale kąty do około 80 stopni lub tak są użyteczne:

Zrzut ekranu przedstawiający stronę Niesymetryczny eksperyment kątowy

Mała ujemna niesymetryczność pozioma może naśladować ukośny lub kursywę tekstu, jak pokazuje strona Ukośny tekst . Klasa ObliqueTextPage pokazuje, jak to zrobić:

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

Właściwość TextAlign właściwości jest ustawiona SKPaint na Center. Bez żadnych przekształceń DrawText wywołanie ze współrzędnymi (0, 0) umieściłoby tekst w poziomie w środku linii bazowej w lewym górnym rogu. Pochylenie SkewDegrees tekstu w poziomie 20 stopni względem punktu odniesienia. Translate Wywołanie przenosi poziome środek linii bazowej tekstu do środka kanwy:

Potrójny zrzut ekranu przedstawiający stronę Tekst ukośny

Na stronie Niesymetryczny tekst w tle pokazano, jak używać kombinacji niesymetryczności 45 stopni i skali pionowej, aby utworzyć cień tekstu, który odchyla się od tekstu. Oto istotnych części PaintSurface programu obsługi:

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

Cień jest wyświetlany najpierw, a następnie tekst:

Potrójny zrzut ekranu przedstawiający stronę Niesymetryczny tekst w tle

Współrzędna pionowa przekazana do DrawText metody wskazuje położenie tekstu względem punktu odniesienia. Jest to ta sama współrzędna pionowa używana do środka niesymetryczności. Ta technika nie będzie działać, jeśli ciąg tekstowy zawiera malejąco. Na przykład zastąp wyraz "dziwactwa" "Shadow", a oto wynik:

Potrójny zrzut ekranu przedstawiający stronę Niesymetryczny tekst w tle z alternatywnym wyrazem malejącym

Cień i tekst są nadal wyrównane do linii bazowej, ale efekt po prostu wygląda źle. Aby rozwiązać ten problem, należy uzyskać ograniczenia tekstowe:

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

Wywołania Translate muszą być dostosowywane przez wysokość malejących:

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

Teraz cień rozciąga się od dołu tych malejących:

Zrzut ekranu przedstawiający stronę Niesymetryczny tekst w tle z korektami dla malejących