次の方法で共有


チュートリアル: 単純な Win2D アプリを構築する

このチュートリアルでは、Win2D の基本的な描画機能の一部について説明します。 次の方法について学習します。

  • WinUI (C#) アプリに Win2D を追加します。
  • テキストとジオメトリを描画します。
  • フィルター効果を適用します。
  • Win2D コンテンツをアニメーション化します。
  • Win2D のベスト プラクティスに従います。

Win2D NuGet パッケージを参照する

  1. 新しい WinUI アプリを作成し、 Microsoft.Graphics.Win2D Nuget パッケージを追加します。

Win2D CanvasControl をアプリの XAML に追加する

  1. Win2D を使用するには、グラフィックスを描画する場所が必要です。 XAML アプリでは、これを行う最も簡単な方法は、XAML ページに CanvasControl を追加することです。

続行する前に、まず、projectのアーキテクチャ オプションが x86 または x64 に設定され、notAny CPU に設定されていることを確認します。 Win2D は C++ で実装されているため、Win2D を使用するプロジェクトは特定の CPU アーキテクチャを対象とする必要があります。

  1. ソリューション エクスプローラーでプロジェクトをダブルクリックして、MainWindow.xamlに移動します。 これにより、ファイルが開きます。 便宜上、[デザイナー] タブの [XAML] ボタンをダブルクリックできます。これにより、ビジュアル デザイナーが非表示になり、コード ビューのすべての領域が予約されます。

  2. コントロールを追加する前に、 まず CanvasControl が定義されている場所を XAML に伝える必要があります。 これを行うには、Window 要素の定義に移動して、次のディレクティブを追加します: xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"。 これで、XAML は次のようになります。

<Window
    ...
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
    mc:Ignorable="d">
  1. 次に、新しい canvas:CanvasControl を子要素としてルート Grid 要素に追加します。 コントロールに名前を付けます (例: "canvas")。 これで、XAML は次のようになります。
<Grid>
    <canvas:CanvasControl x:Name="canvas"/>
</Grid>
  1. 次に、Draw イベントのイベント ハンドラーを定義します。 CanvasControl は、アプリがコンテンツを描画または再描画する必要があるときに常に Draw を発生させます。 最も簡単な方法は、Visual Studioのオートコンプリート機能に支援してもらうことです。 CanvasControl 定義で、Draw イベント ハンドラーの新しい属性の入力を開始します。
<canvas:CanvasControl x:Name="canvas" Draw="canvas_Draw" />

Win2D で最初のテキストを描画する

  1. では、C# のコードの裏側に進みましょう。 Solution Explorerから MainWindow.xaml.cs を開きます。

  2. C# ファイルの先頭には、さまざまな名前空間定義があります。 次の名前空間を追加します。

using Windows.UI;
using System.Numerics;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Effects;
  1. 次に、AutoComplete によって挿入された次の空のイベント ハンドラーが表示されます。
private void canvas_Draw(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
}

(前の手順で AutoComplete を使用しなかった場合は、ここでこのコードを追加してください)。

  1. CanvasDrawEventArgs パラメーターは、型が CanvasDrawingSession であるメンバー DrawingSession を公開します。 このクラスは、Win2D の基本的な描画機能の大部分を提供します。CanvasDrawingSession.DrawRectangle CanvasDrawingSession.DrawImage、およびテキストを描画する必要があるメソッド (CanvasDrawingSession.DrawText

canvas_Draw メソッドに次のコードを追加します。

args.DrawingSession.DrawText("Hello, World!", 100, 100, Colors.Black);

最初の引数 "Hello, World!"は、Win2D に表示する文字列です。 2 つの "100" は、このテキストを 100 DIP (デバイスに依存しないピクセル) で右と下にオフセットするように Win2D に指示します。 最後に、 Colors.Black テキストの色を定義します。

  1. これで、最初の Win2D アプリを実行する準備ができました。 F5 キーを押してコンパイルして起動します。 空のウィンドウとして、「Hello, world!」が黒で表示されているのを見ることが必要です。

Win2D リソースを正しく破棄する

  1. 他の種類のコンテンツを引き出す前に、まず、アプリがメモリ リークを回避できるようにコードを追加する必要があります。 .NET言語で記述され、CanvasControl以下の手順に従う必要があります。 厳密に言えば、単純な "Hello, world" アプリは影響を受けませんが、これは一般的に従うことをお勧めします。

詳細については、「 メモリ リークの回避」を参照してください。

  1. MainWindow.xaml開き、CanvasControl を含む XAML 要素を見つけます。 ファイル内の最初の要素である必要があります。

  2. Unloaded イベントのハンドラーを追加します。 XAML は次のようになります。

<Page
    ...
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
    mc:Ignorable="d"
    Unloaded="Page_Unloaded">
  1. MainWindow.xaml.csに移動し、Page_Unloaded イベント ハンドラーを見つけます。 次のコードを追加します。
void Page_Unloaded(object sender, RoutedEventArgs e)
{
    this.canvas.RemoveFromVisualTree();
    this.canvas = null;
}
  1. アプリに複数の Win2D コントロールが含まれている場合は、Win2D コントロールを含む XAML ページごとに上記の手順を繰り返す必要があります。 現在、アプリには 1 つの CanvasControl しかないため、すべて完了です。

図形を描画する

  1. 2D ジオメトリをアプリに追加するのと同じくらい簡単です。 次のコードを canvas_Draw の末尾に追加します。
args.DrawingSession.DrawCircle(125, 125, 100, Colors.Green);
args.DrawingSession.DrawLine(0, 0, 50, 200, Colors.Red);

これら 2 つのメソッドの引数は、 DrawTextに似ています。 円は、中心点 (125、125)、半径 (100)、色 (緑) によって定義されます。 線は、開始 (0、0)、終了 (50、200) および色 (赤) によって定義されます。

  1. 次に、F5 キーを押してアプリを実行します。 緑色の円と赤い線と共に "Hello, world!" が表示されます。

線の太さや破線などのより高度な描画オプションや、ブラシの使用などのより複雑な塗りつぶしオプションを制御する方法を疑問に思うかもしれません。 Win2D には、これらのオプションがすべて用意されており、必要に応じて簡単に使用できます。 すべてのDraw(...) メソッドには、CanvasTextFormat (フォント ファミリ、サイズなど) や CanvasStrokeStyle (ダッシュ、ドット、エンドキャップなど) などの追加パラメーターを受け取ることができる多くのオーバーロードが用意されています。 これらのオプションの詳細については、API surfaceを参照してください。

描画パラメーターを動的に生成する

  1. 次に、ランダム化された色で図形とテキストの束を描画して、さまざまな種類を追加しましょう。

MainWindow クラスの先頭に次のコードを追加します。 これは、描画時に使用するランダムな値を生成するヘルパー機能です。

Random rnd = new Random();
private Vector2 RndPosition()
{
    double x = rnd.NextDouble() * 500f;
    double y = rnd.NextDouble() * 500f;
    return new Vector2((float)x, (float)y);
}

private float RndRadius()
{
    return (float)rnd.NextDouble() * 150f;
}

private byte RndByte()
{
    return (byte)rnd.Next(256);
}
  1. 次のランダム パラメーターを使用して描画するように canvas_Draw メソッドを変更します。
private void canvas_Draw(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
    args.DrawingSession.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
    args.DrawingSession.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
    args.DrawingSession.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
}

DrawTextがどのように変化したかを分解しましょう。 "Hello, World!" は以前と同じままです。 x および y オフセット パラメーターは、によって生成される 1 つの RndPosition に置き換えられました。 最後に、定義済みの色を使用する代わりに、 Color.FromArgb A、R、G、B の値を使用して色を定義できます。 A はアルファ、または不透明度レベルです。この場合、常に完全に不透明 (255) が必要です。

DrawCircleDrawLineDrawTextと同様に動作します。

  1. 最後に、描画コードを for loop でラップします。 最終的には、次の canvas_Draw コードになります。
for (int i = 0; i < 100; i++)
{
    args.DrawingSession.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
    args.DrawingSession.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
    args.DrawingSession.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
}
  1. アプリをもう一度実行します。 ランダムな位置とサイズを持つテキスト、線、円の束全体が表示されます。

画像効果をコンテンツに適用する

画像効果 (フィルター効果とも呼ばれます) は、ピクセル データに適用されるグラフィカル変換です。 彩度、色相回転、ガウスぼかしは、いくつかの一般的な画像効果です。 画像効果を連結して、最小限の労力で洗練された視覚的な外観を生成できます。

イメージ効果を使用するには、ソース イメージ (開始するコンテンツ) を指定し、GaussianBlurEffect などの効果を作成し、BlurAmount などのプロパティを設定してから、効果の出力を DrawImage で描画します。

テキストや図形に画像効果を適用するには、まずそのコンテンツを CanvasCommandList にレンダリングする必要があります。 このオブジェクトは、効果への入力として使用できます。

  1. 次のコードを使用するように canvas_Draw メソッドを変更します。
CanvasCommandList cl = new CanvasCommandList(sender);

using (CanvasDrawingSession clds = cl.CreateDrawingSession())
{
    for (int i = 0; i < 100; i++)
    {
        clds.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
        clds.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
        clds.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
    }
}

描画できるCanvasDrawingSessionからCanvasDrawEventArgsを取得する方法と同様に、CanvasDrawingSessionからCanvasCommandListを作成できます。 唯一の違いは、コマンド リストの描画セッション (cld) に描画する場合、 CanvasControl に直接レンダリングされないことです。 代わりに、コマンド リストは、後で使用するためにレンダリングの結果を格納する中間オブジェクトです。

コマンド リストの描画セッションをラップする using ブロックに気付いたかもしれません。 描画セッションは IDisposable を実装し、レンダリングが完了したら破棄する必要があります ( using ブロックはこれを行います)。 CanvasDrawingSession から取得した CanvasDrawEventArgs は自動的に閉じられますが、明示的に作成した描画セッションは削除する必要があります。

  1. 最後に、GaussianBlurEffect メソッドの末尾に次のコードを追加して、canvas_Drawを定義します。
GaussianBlurEffect blur = new GaussianBlurEffect();
blur.Source = cl;
blur.BlurAmount = 10.0f;
args.DrawingSession.DrawImage(blur);
  1. アプリをもう一度実行します。 線、テキスト、円がぼやけて見えるはずです。

CanvasAnimatedControl を使用してアプリをアニメーション化する

. Win2D を使用すると、たとえば、すべてのフレームでガウスぼかしのぼかし半径を変更するなどして、コンテンツをリアルタイムで更新およびアニメーション化できます。 これを行うには、CanvasAnimatedControl を使用します。

CanvasControl は、ほとんど静的なグラフィックス コンテンツに最適です。コンテンツを更新または再描画する必要がある場合にのみ、 Draw イベントが発生します。 コンテンツを継続的に変更している場合は、代わりに CanvasAnimatedControl の使用を検討する必要があります。 2 つのコントロールは、 CanvasAnimatedControl が定期的に Draw イベントを発生させる点を除き、非常に同様に動作します。既定では、1 秒あたり 60 回呼び出されます。

  1. CanvasAnimatedControlに切り替えるには、MainPage.xamlに移動し、CanvasControl 行を削除して、次の XAML に置き換えます。
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <canvas:CanvasAnimatedControl x:Name="canvas" Draw="canvas_DrawAnimated" CreateResources="canvas_CreateResources"/>
</Grid>

CanvasControl と同様に、AutoComplete でDrawイベント ハンドラーを作成します。 既定では、canvas_Draw_1 が既に存在するため、Visual Studioではこのハンドラーに canvas_Draw という名前が付けられます。ここでは、メソッドの名前を canvas_AnimatedDraw に変更して、これが別のイベントであることを明確にしました。

さらに、新しいイベント CreateResources も処理します。 もう一度、AutoComplete にハンドラーを作成させます。

アプリが 1 秒あたり 60 フレームで再描画されるようになったので、Win2D ビジュアル リソースを 1 回作成し、フレームごとに再利用する方が効率的です。 コンテンツが静的なままである場合、 CanvasCommandList を作成し、300 個の要素を 1 秒あたり 60 回描画するのは非効率的です。 CreateResources は、ページの読み込み時など、ビジュアル リソースを再作成する必要があると Win2D が判断した場合にのみ発生するイベントです。

  1. MainPage.xaml.csに戻ります。 あなたの canvas_Draw メソッドを、次のように探してください:
private void canvas_Draw(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
    CanvasCommandList cl = new CanvasCommandList(sender);
    using (CanvasDrawingSession clds = cl.CreateDrawingSession())
    {
        for (int i = 0; i < 100; i++)
        {
            clds.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
            clds.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
            clds.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
        }
    }

    GaussianBlurEffect blur = new GaussianBlurEffect();
    blur.Source = cl;
    blur.BlurAmount = 10.0f;
    args.DrawingSession.DrawImage(blur);
}

この既存の描画コードの大部分は、すべてのフレームで実行する必要はありません。テキスト、線、円を含むコマンド リストはすべてのフレームで同じままであり、変更されるのはぼかしの半径だけです。 そのため、この "静的" コードを CreateResourcesに移動できます。

これを行うには、最初にcanvas_Drawの内容全体を最後の行args.DrawingSession.DrawImage(blur);を除いて切り取ります (Ctrl + X)。 不要になった canvas_Draw の残りの部分を削除できるようになりました。 CanvasAnimatedControl には独自の個別の Draw イベントがあることを思い出してください。

  1. 自動生成された canvas_CreateResources メソッドを見つけます。
private void canvas_CreateResources(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedControl sender, 
    Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args)
{}

以前に切り取ったコードをこのメソッドに貼り付けます (Ctrl + V)。 次に、 GaussianBlurEffect の宣言をメソッド本体の外側に移動して、変数が MainPage クラスのメンバーになるようにします。 これでコードは次のようになります。

GaussianBlurEffect blur;
private void canvas_CreateResources(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedControl sender,
    Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args)
{
    CanvasCommandList cl = new CanvasCommandList(sender);
    using (CanvasDrawingSession clds = cl.CreateDrawingSession())
    {
        for (int i = 0; i < 100; i++)
        {
            clds.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
            clds.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
            clds.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
        }
    }

    blur = new GaussianBlurEffect()
    {
        Source = cl,
        BlurAmount = 10.0f
    };
}
  1. ガウスぼかしをアニメーション化できるようになりました。 canvas_DrawAnimated メソッドを見つけて、次のコードを追加します。
private void canvas_DrawAnimated(
    Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender,
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedDrawEventArgs args)
{
    float radius = (float)(1 + Math.Sin(args.Timing.TotalTime.TotalSeconds)) * 10f;
    blur.BlurAmount = radius;
    args.DrawingSession.DrawImage(blur);
}

これにより、CanvasAnimatedDrawEventArgs によって提供される合計経過時間が読み取られ、これを使用して目的のぼかし量が計算されます。サイン関数は、時間の経過に伴う興味深いバリエーションを提供します。 最後に、 GaussianBlurEffect がレンダリングされます。

  1. アプリを実行して、時間の経過に伴うぼやけたコンテンツの変化を確認します。

このクイック スタート チュートリアルを完了しておめでとうございます。 Win2D を使用して、数行の C# コードと XAML コードを使用して、リッチでアニメーション化されたビジュアル シーンを作成する方法を確認できました。