Przekład — przekształcenie
Dowiedz się, jak używać przekształcenia translate w celu przesunięcia grafiki SkiaSharp
Najprostszym typem transformacji w skiaSharp jest transformacja tłumaczenia lub tłumaczenia . Ta transformacja przesuwa obiekty graficzne w kierunkach poziomych i pionowych. W sensie tłumaczenie jest najbardziej niepotrzebnym przekształceniem, ponieważ zwykle można osiągnąć ten sam efekt, zmieniając współrzędne, których używasz w funkcji rysunku. Podczas renderowania ścieżki wszystkie współrzędne są jednak hermetyzowane w ścieżce, więc znacznie łatwiej jest zastosować przekształcenie translacji, aby przesunąć całą ścieżkę.
Tłumaczenie jest również przydatne w przypadku animacji i prostych efektów tekstowych:
Metoda Translate
w metodzie SKCanvas
ma dwa parametry, które powodują późniejsze przesunięcie obiektów graficznych w poziomie i w pionie:
public void Translate (Single dx, Single dy)
Te argumenty mogą być ujemne. Druga Translate
metoda łączy dwie wartości tłumaczenia w jednej SKPoint
wartości:
public void Translate (SKPoint point)
Strona Skumulowane tłumaczenie przykładowego programu pokazuje, że wiele wywołań Translate
metody jest skumulowanych. Klasa AccumulatedTranslatePage
wyświetla 20 wersji tego samego prostokąta, każde przesunięcie z poprzedniego prostokąta wystarczy, aby rozciągnąć wzdłuż przekątnej. Oto procedura obsługi zdarzeń PaintSurface
:
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
using (SKPaint strokePaint = new SKPaint())
{
strokePaint.Color = SKColors.Black;
strokePaint.Style = SKPaintStyle.Stroke;
strokePaint.StrokeWidth = 3;
int rectangleCount = 20;
SKRect rect = new SKRect(0, 0, 250, 250);
float xTranslate = (info.Width - rect.Width) / (rectangleCount - 1);
float yTranslate = (info.Height - rect.Height) / (rectangleCount - 1);
for (int i = 0; i < rectangleCount; i++)
{
canvas.DrawRect(rect, strokePaint);
canvas.Translate(xTranslate, yTranslate);
}
}
}
Kolejne prostokąty wystąpą w dół strony:
Jeśli skumulowane czynniki tłumaczenia to dx
i dy
, a punkt określony w funkcji rysunku to (x
, y
), obiekt graficzny jest renderowany w punkcie (x'
, y'
), gdzie:
x' = x + dx
y' = y + dy
Są one znane jako formuły przekształcania do tłumaczenia. Wartości domyślne dx
i dy
dla nowych SKCanvas
to 0.
Często używa się transformacji translate w przypadku efektów cieni i podobnych technik, jak pokazano na stronie Translate Text Effects (Tłumaczenie efektów tekstowych). Oto odpowiednia PaintSurface
część procedury obsługi w TranslateTextEffectsPage
klasie:
float textSize = 150;
using (SKPaint textPaint = new SKPaint())
{
textPaint.Style = SKPaintStyle.Fill;
textPaint.TextSize = textSize;
textPaint.FakeBoldText = true;
float x = 10;
float y = textSize;
// Shadow
canvas.Translate(10, 10);
textPaint.Color = SKColors.Black;
canvas.DrawText("SHADOW", x, y, textPaint);
canvas.Translate(-10, -10);
textPaint.Color = SKColors.Pink;
canvas.DrawText("SHADOW", x, y, textPaint);
y += 2 * textSize;
// Engrave
canvas.Translate(-5, -5);
textPaint.Color = SKColors.Black;
canvas.DrawText("ENGRAVE", x, y, textPaint);
canvas.ResetMatrix();
textPaint.Color = SKColors.White;
canvas.DrawText("ENGRAVE", x, y, textPaint);
y += 2 * textSize;
// Emboss
canvas.Save();
canvas.Translate(5, 5);
textPaint.Color = SKColors.Black;
canvas.DrawText("EMBOSS", x, y, textPaint);
canvas.Restore();
textPaint.Color = SKColors.White;
canvas.DrawText("EMBOSS", x, y, textPaint);
}
W każdym z trzech przykładów Translate
wywoływana jest funkcja wyświetlania tekstu w celu przesunięcia go z lokalizacji podanej x
przez zmienne i y
. Następnie tekst zostanie ponownie wyświetlony w innym kolorze bez efektu tłumaczenia:
Każdy z trzech przykładów pokazuje inny sposób negowania wywołania Translate
:
Pierwszy przykład po prostu wywołuje ponownie, Translate
ale z wartościami ujemnymi. Translate
Ponieważ wywołania są skumulowane, ta sekwencja wywołań po prostu przywraca całkowite tłumaczenie do wartości domyślnych zera.
Drugi przykład wywołuje metodę ResetMatrix
. Spowoduje to powrót wszystkich przekształceń do stanu domyślnego.
Trzeci przykład zapisuje stan SKCanvas
obiektu za pomocą wywołania metody Save
, a następnie przywraca stan za pomocą wywołania metody Restore
. Jest to najbardziej wszechstronny sposób manipulowania transformacjami dla serii operacji rysowania. Te Save
metody i Restore
wywołania działają jak stos: można wywołać Save
wiele razy, a następnie wywołać Restore
metodę w odwrotnej kolejności, aby powrócić do poprzednich stanów. Metoda Save
zwraca liczbę całkowitą i można przekazać tę liczbę całkowitą, aby RestoreToCount
skutecznie wywoływać Restore
wiele razy. Właściwość SaveCount
zwraca liczbę stanów aktualnie zapisanych na stosie.
Możesz również użyć SKAutoCanvasRestore
klasy do przywrócenia stanu kanwy. Konstruktor tej klasy ma być wywoływany w using
instrukcji; stan kanwy jest automatycznie przywracany na końcu using
bloku.
Nie musisz jednak martwić się o przekształcenia przenoszone z jednego wywołania PaintSurface
programu obsługi do następnego. Każde nowe wywołanie zapewnia PaintSurface
nowy SKCanvas
obiekt z domyślnymi przekształceniami.
Innym typowym zastosowaniem Translate
transformacji jest renderowanie obiektu wizualnego, który został pierwotnie utworzony przy użyciu współrzędnych, które są wygodne do rysowania. Na przykład można określić współrzędne zegara analogowego z środek w punkcie (0, 0). Następnie możesz użyć przekształceń, aby wyświetlić zegar, w którym chcesz. Ta technika jest pokazana na stronie [Tablica Hendecagram]. Klasa HendecagramArrayPage
zaczyna się od utworzenia SKPath
obiektu dla 11-punktowej gwiazdki. Obiekt HendecagramPath
jest definiowany jako publiczny, statyczny i tylko do odczytu, dzięki czemu można uzyskać do niego dostęp z innych programów demonstracyjnych. Jest on tworzony w konstruktorze statycznym:
public class HendecagramArrayPage : ContentPage
{
...
public static readonly SKPath HendecagramPath;
static HendecagramArrayPage()
{
// Create 11-pointed star
HendecagramPath = new SKPath();
for (int i = 0; i < 11; i++)
{
double angle = 5 * i * 2 * Math.PI / 11;
SKPoint pt = new SKPoint(100 * (float)Math.Sin(angle),
-100 * (float)Math.Cos(angle));
if (i == 0)
{
HendecagramPath.MoveTo(pt);
}
else
{
HendecagramPath.LineTo(pt);
}
}
HendecagramPath.Close();
}
}
Jeśli środek gwiazdy jest punktem (0, 0), wszystkie punkty gwiazdy znajdują się w okręgu wokół tego punktu. Każdy punkt jest kombinacją sinusu i cosinus wartości kąta, który zwiększa się o 5/11 i 360 stopni. (Można również utworzyć 11-punktową gwiazdę, zwiększając kąt o 2/11, 3/11 lub 4/11 okręgu). Promień tego okręgu jest ustawiony na 100.
Jeśli ta ścieżka jest renderowana bez żadnych przekształceń, środek zostanie umieszczony w lewym górnym rogu SKCanvas
obiektu , a tylko jedna czwarta będzie widoczna. Program PaintSurface
obsługi HendecagramPage
zamiast tego używa Translate
elementu do kafelka kanwy z wieloma kopiami gwiazdy, z których każda jest losowo kolorowana:
public class HendecagramArrayPage : ContentPage
{
Random random = new Random();
...
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
using (SKPaint paint = new SKPaint())
{
for (int x = 100; x < info.Width + 100; x += 200)
for (int y = 100; y < info.Height + 100; y += 200)
{
// Set random color
byte[] bytes = new byte[3];
random.NextBytes(bytes);
paint.Color = new SKColor(bytes[0], bytes[1], bytes[2]);
// Display the hendecagram
canvas.Save();
canvas.Translate(x, y);
canvas.DrawPath(HendecagramPath, paint);
canvas.Restore();
}
}
}
}
Oto wynik:
Animacje często obejmują przekształcenia. Strona Animacja Hendecagram przenosi 11-punktową gwiazdę wokół w okręgu. Klasa HendecagramAnimationPage
rozpoczyna się od niektórych pól i przesłonięć OnAppearing
metod i OnDisappearing
, aby uruchomić i zatrzymać Xamarin.Forms czasomierz:
public class HendecagramAnimationPage : ContentPage
{
const double cycleTime = 5000; // in milliseconds
SKCanvasView canvasView;
Stopwatch stopwatch = new Stopwatch();
bool pageIsActive;
float angle;
public HendecagramAnimationPage()
{
Title = "Hedecagram Animation";
canvasView = new SKCanvasView();
canvasView.PaintSurface += OnCanvasViewPaintSurface;
Content = canvasView;
}
protected override void OnAppearing()
{
base.OnAppearing();
pageIsActive = true;
stopwatch.Start();
Device.StartTimer(TimeSpan.FromMilliseconds(33), () =>
{
double t = stopwatch.Elapsed.TotalMilliseconds % cycleTime / cycleTime;
angle = (float)(360 * t);
canvasView.InvalidateSurface();
if (!pageIsActive)
{
stopwatch.Stop();
}
return pageIsActive;
});
}
protected override void OnDisappearing()
{
base.OnDisappearing();
pageIsActive = false;
}
...
}
Pole angle
jest animowane od 0 stopni do 360 stopni co 5 sekund. Procedura PaintSurface
obsługi używa angle
właściwości na dwa sposoby: aby określić odcienie koloru w metodzie SKColor.FromHsl
, oraz jako argument Math.Sin
metody i Math.Cos
do zarządzania lokalizacją gwiazdy:
public class HendecagramAnimationPage : ContentPage
{
...
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
canvas.Translate(info.Width / 2, info.Height / 2);
float radius = (float)Math.Min(info.Width, info.Height) / 2 - 100;
using (SKPaint paint = new SKPaint())
{
paint.Style = SKPaintStyle.Fill;
paint.Color = SKColor.FromHsl(angle, 100, 50);
float x = radius * (float)Math.Sin(Math.PI * angle / 180);
float y = -radius * (float)Math.Cos(Math.PI * angle / 180);
canvas.Translate(x, y);
canvas.DrawPath(HendecagramPage.HendecagramPath, paint);
}
}
}
Procedura PaintSurface
obsługi wywołuje metodę Translate
dwa razy, najpierw, aby przetłumaczyć na środek kanwy, a następnie przetłumaczyć na obwód okręgu wyśrodkowanego wokół (0, 0). Promień okręgu jest tak duży, jak to możliwe, zachowując gwiazdę w granicach strony:
Zwróć uwagę, że gwiazda zachowuje taką samą orientację, jak obraca się wokół środka strony. Nie obraca się w ogóle. Jest to zadanie przekształcenia rotacji.