次の方法で共有


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 つのプロパティがあります。

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 で実行されているプログラムを次に示します。

[Simple Circle] ページのトリプル スクリーンショット

プログラムを自分で実行しているなら、スマートフォンまたはシミュレーターを横向きにして、グラフィックがどのように再描画されるかを確認できます。 グラフィックを再描画する必要があるたびに、PaintSurface イベント ハンドラーが再度呼び出されます。

グラデーションやビットマップ タイルを使って、グラフィック オブジェクトに色を付けることもできます。 これらのオプションについては、SkiaSharp シェーダー」に関するセクションで説明します。

SKPaint オブジェクトは、グラフィックス描画プロパティのコレクションに過ぎません。 これらのオブジェクトは軽量です。 このプログラムで行っているように SKPaint オブジェクトを再利用することも、描画プロパティのさまざまな組み合わせに対して複数の SKPaint オブジェクトを作成することもできます。 これらのオブジェクトは PaintSurface イベント ハンドラーの外部で作成して初期化でき、ページ クラスのフィールドとして保存できます。

Note

SKPaint クラスで定義されている IsAntialias は、グラフィックスのレンダリングでアンチエイリアシングを有効にします。 アンチエイリアシングを行うと、通常、エッジの見た目が滑らかになるため、おそらく、ほとんどの SKPaint オブジェクトでこのプロパティを true に設定したくなります。 わかりやすくするため、このプロパティはほとんどのサンプル ページで設定されていません。

円の枠線の幅は 25 ピクセル (つまり、円の半径の 4 分の 1) と指定されていますが、細すぎるように見えます。これにはもっともな理由があり、線の幅の半分は青い円で隠されています。 DrawCircle メソッドの引数では、円の抽象的な幾何学的座標を定義します。 青色の内部のサイズは最も近いピクセルに合わせて設定されますが、25 ピクセル幅の枠線は幾何学的な円にまたがっており、半分は内側、半分は外側にあります。

Xamarin.Forms との統合」記事の次のサンプルでは、これを視覚的に見ていきます。