Piksele i jednostki niezależne od urządzenia
Poznaj różnice między współrzędnymi SkiaSharp i Xamarin.Forms współrzędnymi
W tym artykule przedstawiono różnice w układzie współrzędnych używanym w systemach SkiaSharp i Xamarin.Forms. Możesz uzyskać informacje umożliwiające konwersję między dwoma układami współrzędnych, a także narysować grafiki, które wypełniają określony obszar:
Jeśli programujesz od Xamarin.Forms jakiegoś czasu, możesz mieć poczucie Xamarin.Forms współrzędnych i rozmiarów. Okręgi rysowane w dwóch poprzednich artykułach mogą wydawać się nieco małe dla Ciebie.
Te okręgi są małe w porównaniu z rozmiarami Xamarin.Forms . Domyślnie skiaSharp rysuje jednostki pikseli, podczas gdy Xamarin.Forms podstawy koordynują i rozmiary w jednostce niezależnej od urządzenia ustanowionej przez podstawową platformę. (Więcej informacji na Xamarin.Forms temat układu współrzędnych można znaleźć w rozdziale 5. Praca z rozmiarami książki Creating Mobile Apps with Xamarin.Forms.)
Strona w programie przykładowym zatytułowanym Surface Size używa danych wyjściowych tekstu SkiaSharp w celu wyświetlenia rozmiaru powierzchni ekranu z trzech różnych źródeł:
- Normalne Xamarin.Forms
Width
iHeight
właściwościSKCanvasView
obiektu. - Właściwość
CanvasSize
SKCanvasView
obiektu. - Właściwość
Size
SKImageInfo
wartości, która jest zgodna z właściwościamiWidth
iHeight
używanymi na dwóch poprzednich stronach.
Klasa SurfaceSizePage
pokazuje, jak wyświetlić te wartości. Konstruktor zapisuje SKCanvasView
obiekt jako pole, aby można było uzyskać do niego dostęp w programie obsługi zdarzeń PaintSurface
:
SKCanvasView canvasView;
public SurfaceSizePage()
{
Title = "Surface Size";
canvasView = new SKCanvasView();
canvasView.PaintSurface += OnCanvasViewPaintSurface;
Content = canvasView;
}
SKCanvas
zawiera sześć różnych DrawText
metod, ale ta DrawText
metoda jest najprostsza:
public void DrawText (String text, Single x, Single y, SKPaint paint)
Należy określić ciąg tekstowy, współrzędne X i Y, w których tekst ma się rozpocząć, oraz SKPaint
obiekt. Współrzędna X określa, gdzie jest umieszczona lewa strona tekstu, ale zwróć uwagę: Współrzędna Y określa położenie punktu odniesienia tekstu. Jeśli kiedykolwiek napisałeś ręcznie na papierze liniowym, linia bazowa to linia, w której znajdują się znaki, i poniżej, które maleją (takie jak litery g, p, q i y) maleją.
Obiekt SKPaint
umożliwia określenie koloru tekstu, rodziny czcionek i rozmiaru tekstu. Domyślnie TextSize
właściwość ma wartość 12, co powoduje niewielki tekst na urządzeniach o wysokiej rozdzielczości, takich jak telefony. W dowolnych aplikacjach, ale najprostszych, będziesz również potrzebować pewnych informacji na temat rozmiaru wyświetlanego tekstu. Klasa SKPaint
definiuje FontMetrics
właściwość i kilka MeasureText
metod, ale w przypadku mniej fantazyjnego zapotrzebowania FontSpacing
właściwość zapewnia zalecaną wartość dla odstępów między kolejnymi wierszami tekstu.
Poniższa PaintSurface
procedura obsługi tworzy SKPaint
obiekt dla TextSize
40 pikseli, który jest żądaną pionową wysokością tekstu od góry rosnąco do dołu malejących. Wartość FontSpacing
zwracana przez SKPaint
obiekt jest nieco większa niż, około 47 pikseli.
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
SKPaint paint = new SKPaint
{
Color = SKColors.Black,
TextSize = 40
};
float fontSpacing = paint.FontSpacing;
float x = 20; // left margin
float y = fontSpacing; // first baseline
float indent = 100;
canvas.DrawText("SKCanvasView Height and Width:", x, y, paint);
y += fontSpacing;
canvas.DrawText(String.Format("{0:F2} x {1:F2}",
canvasView.Width, canvasView.Height),
x + indent, y, paint);
y += fontSpacing * 2;
canvas.DrawText("SKCanvasView CanvasSize:", x, y, paint);
y += fontSpacing;
canvas.DrawText(canvasView.CanvasSize.ToString(), x + indent, y, paint);
y += fontSpacing * 2;
canvas.DrawText("SKImageInfo Size:", x, y, paint);
y += fontSpacing;
canvas.DrawText(info.Size.ToString(), x + indent, y, paint);
}
Metoda rozpoczyna pierwszy wiersz tekstu ze współrzędną X 20 (dla małego marginesu po lewej stronie) i współrzędną fontSpacing
Y , która jest nieco większa niż to, co jest konieczne do wyświetlenia pełnej wysokości pierwszego wiersza tekstu w górnej części powierzchni wyświetlania. Po każdym wywołaniu metody DrawText
współrzędna Y jest zwiększana o jeden lub dwa przyrosty fontSpacing
.
Oto uruchomiony program:
Jak widać, CanvasSize
właściwość SKCanvasView
i Size
właściwość SKImageInfo
wartości są spójne w raportowaniu wymiarów pikseli. Właściwości Height
SKCanvasView
i Width
to właściwości Xamarin.Forms oraz raportują rozmiar widoku w jednostkach niezależnych od urządzenia zdefiniowanych przez platformę.
Symulator systemu iOS po lewej stronie ma dwa piksele na jednostkę niezależną od urządzenia, a android Nexus 5 w środku ma trzy piksele na jednostkę. Dlatego pokazany wcześniej prosty okrąg ma różne rozmiary na różnych platformach.
Jeśli wolisz pracować całkowicie w jednostkach niezależnych od urządzenia, możesz to zrobić, ustawiając IgnorePixelScaling
właściwość na SKCanvasView
true
wartość . Jednak wyniki mogą się nie podobać. SkiaSharp renderuje grafikę na mniejszej powierzchni urządzenia z rozmiarem pikseli równym rozmiarowi widoku w jednostkach niezależnych od urządzenia. (Na przykład SkiaSharp będzie używać powierzchni ekranu 360 x 512 pikseli na Nexus 5. Następnie skaluje w górę ten obraz o rozmiarze, co powoduje zauważalne jaggies mapy bitowej.
Aby zachować tę samą rozdzielczość obrazu, lepszym rozwiązaniem jest napisanie własnych prostych funkcji do konwersji między dwoma układami współrzędnych.
Oprócz DrawCircle
metody definiuje również dwie DrawOval
metody, SKCanvas
które rysują wielokropek. Wielokropek jest definiowany przez dwa promienie, a nie jeden promień. Są one znane jako główny promień i mniejszy promień. Metoda DrawOval
rysuje wielokropek z dwoma promieniami równoległymi do osi X i Y. (Jeśli musisz narysować wielokropek z osiami, które nie są równoległe do osi X i Y, możesz użyć przekształcenia obrotu zgodnie z opisem w artykule Obracanie transformacji lub ścieżki grafiki zgodnie z opisem w artykule Trzy sposoby rysowania łuku). To przeciążenie DrawOval
metody nazywa dwa parametry rx
promieniowe i ry
wskazuje, że są one równoległe do osi X i Y:
public void DrawOval (Single cx, Single cy, Single rx, Single ry, SKPaint paint)
Czy można narysować wielokropek, który wypełnia powierzchnię wyświetlacza? Na stronie Wypełnienie wielokropka pokazano, jak to zrobić. Procedura PaintSurface
obsługi zdarzeń w klasie EllipseFillPage.xaml.cs odejmuje połowę szerokości pociągnięcia od xRadius
wartości i yRadius
w celu dopasowania całej wielokropka i jej konturu na powierzchni ekranu:
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
float strokeWidth = 50;
float xRadius = (info.Width - strokeWidth) / 2;
float yRadius = (info.Height - strokeWidth) / 2;
SKPaint paint = new SKPaint
{
Style = SKPaintStyle.Stroke,
Color = SKColors.Blue,
StrokeWidth = strokeWidth
};
canvas.DrawOval(info.Width / 2, info.Height / 2, xRadius, yRadius, paint);
}
W tym miejscu działa:
Druga DrawOval
metoda ma SKRect
argument, który jest prostokątem zdefiniowanym pod względem współrzędnych X i Y w lewym górnym rogu i prawym dolnym rogu. Owalu wypełnia ten prostokąt, co sugeruje, że może być możliwe użycie go na stronie Wypełnienie wielokropka w następujący sposób:
SKRect rect = new SKRect(0, 0, info.Width, info.Height);
canvas.DrawOval(rect, paint);
Jednak to obcina wszystkie krawędzie konturu wielokropka po czterech stronach. Aby wykonać tę pracę, musisz dostosować wszystkie SKRect
argumenty konstruktora na strokeWidth
podstawie elementu :
SKRect rect = new SKRect(strokeWidth / 2,
strokeWidth / 2,
info.Width - strokeWidth / 2,
info.Height - strokeWidth / 2);
canvas.DrawOval(rect, paint);