Çeviri Dönüşümü
SkiaSharp grafiklerini kaydırmak için çeviri dönüşümünü kullanmayı öğrenin
SkiaSharp'taki en basit dönüşüm türü çeviri veya çeviri dönüşümüdür. Bu dönüşüm, grafik nesneleri yatay ve dikey yönde kaydırıyor. Bir anlamda çeviri en gereksiz dönüşümdür çünkü genellikle çizim işlevinde kullandığınız koordinatları değiştirerek aynı etkiyi gerçekleştirebilirsiniz. Ancak bir yol işlenirken, tüm koordinatlar yolda kapsüllenir, bu nedenle tüm yolu kaydırmak için çeviri dönüşümü uygulamak çok daha kolaydır.
Çeviri, animasyon ve basit metin efektleri için de kullanışlıdır:
yöntemindeSKCanvas
, Translate
daha sonra çizilen grafik nesnelerinin yatay ve dikey olarak kaydırılmasına neden olan iki parametre vardır:
public void Translate (Single dx, Single dy)
Bu bağımsız değişkenler negatif olabilir. İkinci Translate
bir yöntem, iki çeviri değerini tek SKPoint
bir değerde birleştirir:
public void Translate (SKPoint point)
Örnek programın Birikmiş Çeviri sayfası, yöntemin birden çok çağrısının Translate
birikmeli olduğunu gösterir. sınıfı, AccumulatedTranslatePage
aynı dikdörtgenin 20 sürümünü görüntüler ve her biri bir önceki dikdörtgenden köşegen boyunca esnetilecek kadar uzaklık gösterir. Olay işleyicisi aşağıdadır 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);
}
}
}
Birbirini izleyen dikdörtgenler sayfayı daraltır:
Birikmiş çeviri faktörleri dx
ve dy
ise ve bir çizim işlevinde belirttiğiniz nokta (x
, ) ise grafik y
nesne şu noktada (x'
, y'
), burada işlenir:
x' = x + dx
y' = y + dy
Bunlar çeviri için dönüştürme formülleri olarak bilinir. Yeni SKCanvas
için ve dy
varsayılan değerleri dx
0'dır.
Metin Efektlerini Çevir sayfasında gösterildiği gibi, gölge efektleri ve benzer teknikler için çeviri dönüşümünü kullanmak yaygın bir yöntemdir. sınıfındaki işleyicinin PaintSurface
ilgili bölümü aşağıdadır TranslateTextEffectsPage
:
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);
}
Üç örneğin her birinde, Translate
ve y
değişkenleri tarafından x
verilen konumdan uzaklık için metni görüntülemek için çağrılır. Daha sonra metin, çeviri etkisi olmadan başka bir renkte yeniden görüntülenir:
Üç örnekten her biri çağrıyı olumsuzlamanın Translate
farklı bir yolunu gösterir:
İlk örnek yalnızca negatif değerlerle yeniden çağırır Translate
. Translate
Çağrılar birikmeli olduğundan, bu çağrı dizisi toplam çeviriyi varsayılan sıfır değerlerine geri yükler.
İkinci örnek öğesini çağırır ResetMatrix
. Bu, tüm dönüşümlerin varsayılan durumlarına dönmesine neden olur.
Üçüncü örnek, öğesinin çağrısıyla Save
nesnenin SKCanvas
durumunu kaydeder ve ardından çağrısıyla Restore
durumunu geri yükler. Bu, bir dizi çizim işlemi için dönüşümleri işlemenin en çok yönlü yoludur. Bunlar Save
ve Restore
çağrıları bir yığın gibi çalışır: Birden çok kez çağırabilir Save
ve ardından önceki durumlara dönmek için ters sırayla çağırabilirsiniz Restore
. Save
yöntemi bir tamsayı döndürür ve birden çok kez etkili bir şekilde çağırmak Restore
için bu tamsayıyı öğesine RestoreToCount
geçirebilirsiniz. özelliği, SaveCount
yığına kaydedilmiş durumdaki durum sayısını döndürür.
Tuval durumunu geri yüklemek için sınıfını da kullanabilirsiniz SKAutoCanvasRestore
. Bu sınıfın oluşturucusunun deyiminde using
çağrılmak üzere tasarlanması amaçlanmıştır; tuval durumu bloğun using
sonunda otomatik olarak geri yüklenir.
Ancak, işleyicinin bir çağrısından PaintSurface
diğerine taşıma dönüşümleri konusunda endişelenmeniz gerekmez. Her yeni çağrısı PaintSurface
, varsayılan dönüşümlere sahip yeni SKCanvas
bir nesne sunar.
Dönüşümün Translate
bir diğer yaygın kullanımı, başlangıçta çizim için uygun koordinatlar kullanılarak oluşturulmuş bir görsel nesneyi işlemektir. Örneğin, noktada ortalanmış bir analog saat için koordinatlar belirtmek isteyebilirsiniz (0, 0). Ardından dönüşümleri kullanarak saati istediğiniz yerde görüntüleyebilirsiniz. Bu teknik [Hendecagram Dizisi] sayfasında gösterilmiştir. sınıfı, HendecagramArrayPage
11 noktalı yıldız için bir SKPath
nesne oluşturarak başlar. Nesnesi HendecagramPath
genel, statik ve salt okunur olarak tanımlanır, böylece diğer tanıtım programlarından erişilebilir. Statik bir oluşturucuda oluşturulur:
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();
}
}
Yıldızın merkezi nokta (0, 0) ise, yıldızın tüm noktaları bu noktayı çevreleyen bir daire üzerindedir. Her nokta, 360 derecenin 5/11'inde artan bir açının sinüs ve kosinüs değerlerinin birleşimidir. (Açıyı 11/2, 3/11 veya dairenin 11/4'ünde artırarak 11 köşeli yıldız da oluşturabilirsiniz.) Bu dairenin yarıçapı 100 olarak ayarlanmıştır.
Bu yol herhangi bir dönüşüm olmadan işlenirse, merkez öğesinin SKCanvas
sol üst köşesine konumlandırılır ve yalnızca dörtte biri görünür. bunun PaintSurface
yerine işleyicisi HendecagramPage
tuvali, her biri rastgele renkli olan birden çok yıldız kopyasıyla döşemek için kullanır Translate
:
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();
}
}
}
}
Sonuç şu şekildedir:
Animasyonlar genellikle dönüşümleri içerir. Hendekagram Animasyon sayfası, 11 noktalı yıldızı daire içinde hareket eder. sınıfı, HendecagramAnimationPage
zamanlayıcıyı Xamarin.Forms başlatmak ve durdurmak için ve OnDisappearing
yöntemlerinin OnAppearing
bazı alanları ve geçersiz kılmalarıyla başlar:
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;
}
...
}
Alan angle
her 5 saniyede bir 0 dereceden 360 dereceye kadar animasyonludur. İşleyici PaintSurface
özelliğini iki şekilde kullanır angle
: yöntemindeki SKColor.FromHsl
rengin tonunu belirtmek için ve yıldızın konumunu idare etmek için Math.Sin
ve Math.Cos
yöntemlerine bağımsız değişken olarak:
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);
}
}
}
İşleyici PaintSurface
, önce tuvalin ortasına çevirmek ve ardından yaklaşık ortalanmış bir dairenin çevresine çevirmek için yöntemini iki kez çağırır Translate
(0, 0). Dairenin yarıçapı, yıldızı sayfanın sınırları içinde tutmaya devam ederken mümkün olduğunca büyük olacak şekilde ayarlanır:
Yıldızın sayfanın ortasında döndürdüğü yönün aynısını koruduğuna dikkat edin. Hiç dönmez. Bu, dönüşüm döndürme işidir.