SkiaSharp での単純な円の描画
キャンバスやペイント オブジェクトなど、SkiaSharp での描画の基本について説明します
この記事では、グラフィックスをホストするための SKCanvasView
オブジェクトの作成、PaintSurface
イベントの処理、SKPaint
オブジェクトを使って色や他の描画属性を指定する方法など、SkiaSharp を使用した Xamarin.Forms でのグラフィックスの描画の概念について説明します。
サンプル プログラムには、この SkiaSharp 記事シリーズのすべてのサンプル コードが含まれています。 最初のページは Simple Circle というタイトルで、ページ クラス SimpleCirclePage
を呼び出します。 このコードでは、ページの中央に半径 100 ピクセルの円を描画する方法が示されています。 円の枠線は赤で、円の内部は青です。
SimpleCircle
ページ クラスは ContentPage
から派生し、SkiaSharp 名前空間の 2 つの using
ディレクティブを含みます。
using SkiaSharp;
using SkiaSharp.Views.Forms;
このクラスの次のコンストラクターは、SKCanvasView
オブジェクトを作成し、PaintSurface
イベントのハンドラーをアタッチし、ページのコンテンツとして SKCanvasView
オブジェクトを設定します。
public SimpleCirclePage()
{
Title = "Simple Circle";
SKCanvasView canvasView = new SKCanvasView();
canvasView.PaintSurface += OnCanvasViewPaintSurface;
Content = canvasView;
}
SKCanvasView
は、ページのコンテンツ領域全体を占めます。 他の例で目にするように、代わりに SKCanvasView
を他の Xamarin.FormsView
派生物と組み合わせることもできます。
PaintSurface
イベント ハンドラーは、すべての描画を行う場所です。 このメソッドは、プログラムの実行中に何回でも呼び出せるので、グラフィックスの表示を作り直すために必要なすべての情報を保持する必要があります。
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
...
}
イベントに付随する SKPaintSurfaceEventArgs
オブジェクトには、2 つのプロパティがあります。
Info
(SKImageInfo
型)Surface
(SKSurface
型)
SKImageInfo
構造体には、描画サーフェイスに関する情報が格納されており、最も重要なのはその幅と高さ (ピクセル単位) です。 SKSurface
オブジェクトは、描画サーフェイス自体を表します。 このプログラムでの描画サーフェイスはビデオ表示ですが、他のプログラムの SKSurface
オブジェクトでは、SkiaSharp を使って描画するビットマップを表すこともできます。
SKSurface
の最も重要なプロパティは、SKCanvas
型の Canvas
です。 このクラスは、実際の描画を実行するために使うグラフィックス描画コンテキストです。 SKCanvas
オブジェクトはグラフィックスの状態をカプセル化しており、それにはグラフィックスの変換とクリッピングが含まれます。
PaintSurface
イベント ハンドラーの一般的な最初の状態を次に示します。
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
...
}
Clear
メソッドは、透明な色でキャンバスをクリアします。 オーバーロードを使って、キャンバスの背景色を指定できます。
ここでの目標は、青で塗りつぶされた赤い円を描くことです。 この特定のグラフィック イメージには 2 つの異なる色が含まれているため、このジョブは 2 つのステップで行う必要があります。 最初のステップでは、円の輪郭を描画します。 線の色と他の特性を指定するため、SKPaint
オブジェクトを作成して初期化します。
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
...
SKPaint paint = new SKPaint
{
Style = SKPaintStyle.Stroke,
Color = Colors.Red.ToSKColor(),
StrokeWidth = 25
};
...
}
Style
プロパティは、内側を "塗りつぶす" のではなく、線 (この場合は円の枠線) の "ストロークを描く" ことを示します。 SKPaintStyle
列挙型の 3 つのメンバーは次のとおりです。
既定値は、Fill
です。 線のストロークを描き、内部を同じ色で塗りつぶすには、3 番目のオプションを使います。
Color
プロパティを SKColor
型の値に設定します。 SKColor
の値を取得する方法の 1 つは、拡張メソッド ToSKColor
を使って、Xamarin.FormsColor
の値を SKColor
の値に変換する方法です。 SkiaSharp.Views.Forms
名前空間の Extensions
クラスには、Xamarin.Forms 値と SkiaSharp 値の間で変換を行う他のメソッドが含まれます。
StrokeWidth
プロパティは、線の太さを示します。 ここでは、25 ピクセルに設定されています。
その SKPaint
オブジェクトを使って円を描画します。
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
...
canvas.DrawCircle(info.Width / 2, info.Height / 2, 100, paint);
...
}
座標は、表示サーフェイスの左上隅を基準にして指定します。 X 座標は右に向かって増加し、Y 座標は下に向かって増加します。 グラフィックスに関する説明では、(x、y) という数学的表記を使って点を示すことがよくあります。 点 (0, 0) は表示サーフェイスの左上隅であり、多くの場合、"原点" と呼ばれます。
DrawCircle
の最初の 2 つの引数は、円の中心の X および Y 座標を示します。 これらには表示サーフェイスの幅と高さの半分が割り当てられており、表示サーフェイスの中心に円の中心が配置されます。 3 番目の引数は円の半径を指定し、最後の引数は SKPaint
オブジェクトです。
円の内部を塗りつぶすには、SKPaint
オブジェクトの 2 つのプロパティを変更して、DrawCircle
をもう一度呼び出します。 このコードは、SKColors
構造体の多くのフィールドの 1 つから SKColor
値を取得する別の方法も示しています。
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
...
paint.Style = SKPaintStyle.Fill;
paint.Color = SKColors.Blue;
canvas.DrawCircle(args.Info.Width / 2, args.Info.Height / 2, 100, paint);
}
今度の DrawCircle
の呼び出しでは、SKPaint
オブジェクトの新しいプロパティを使って円が塗りつぶされます。
iOS と Android で実行されているプログラムを次に示します。
プログラムを自分で実行しているなら、スマートフォンまたはシミュレーターを横向きにして、グラフィックがどのように再描画されるかを確認できます。 グラフィックを再描画する必要があるたびに、PaintSurface
イベント ハンドラーが再度呼び出されます。
グラデーションやビットマップ タイルを使って、グラフィック オブジェクトに色を付けることもできます。 これらのオプションについては、SkiaSharp シェーダー」に関するセクションで説明します。
SKPaint
オブジェクトは、グラフィックス描画プロパティのコレクションに過ぎません。 これらのオブジェクトは軽量です。 このプログラムで行っているように SKPaint
オブジェクトを再利用することも、描画プロパティのさまざまな組み合わせに対して複数の SKPaint
オブジェクトを作成することもできます。 これらのオブジェクトは PaintSurface
イベント ハンドラーの外部で作成して初期化でき、ページ クラスのフィールドとして保存できます。
Note
SKPaint
クラスで定義されている IsAntialias
は、グラフィックスのレンダリングでアンチエイリアシングを有効にします。 アンチエイリアシングを行うと、通常、エッジの見た目が滑らかになるため、おそらく、ほとんどの SKPaint
オブジェクトでこのプロパティを true
に設定したくなります。 わかりやすくするため、このプロパティはほとんどのサンプル ページで設定されていません。
円の枠線の幅は 25 ピクセル (つまり、円の半径の 4 分の 1) と指定されていますが、細すぎるように見えます。これにはもっともな理由があり、線の幅の半分は青い円で隠されています。 DrawCircle
メソッドの引数では、円の抽象的な幾何学的座標を定義します。 青色の内部のサイズは最も近いピクセルに合わせて設定されますが、25 ピクセル幅の枠線は幾何学的な円にまたがっており、半分は内側、半分は外側にあります。
「Xamarin.Forms との統合」記事の次のサンプルでは、これを視覚的に見ていきます。