共有UIコンポーネントの作成
次に、画像生成アプリに必要なUIコンポーネントを作成していきましょう。今回は、ImageGenerator.Sharedプロジェクトに共通のUIコンポーネントを実装します。
@injectアノテーション
まず、プロジェクトが生成されたときに作成される、デフォルトのコンポーネントを確認しておきましょう。ImageGenerator.SharedプロジェクトのPagesフォルダにあるHome.razorでは、次の通りシンプルなページが定義されています。
@page "/" @using ImageGenerator.Shared.Services @inject IFormFactor FormFactor ~後略~
このコンポーネントの先頭では、@usingアノテーションで名前空間が追加され、@injectアノテーションでFormFactorサービスが注入(インジェクション)されています。これは依存性注入(DI)と呼ばれる手法で、コンポーネントが直接サービスのインスタンスを作成するのではなく、フレームワークから提供されるサービスを利用できるようにするものです。FormFactorサービスについては、後ほど詳しく解説します。
コンポーネントの追加
では、画像生成アプリに必要な独自のコンポーネントを追加していきましょう。
まずは、画像生成ページを作成します。ソリューションエクスプローラーで、ImageGenerator.Sharedプロジェクト内のPagesフォルダを右クリックします。そして[追加]-[Razorコンポーネント]を選択し、名前をImageGeneration.razorにします。
生成されたファイルの先頭にある <h3>タグの行を削除して、代わりに次のコードを記述します。
@page "/generate"
<PageTitle>画像生成</PageTitle>
<h1>AI画像生成</h1>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="prompt">プロンプト</label>
<textarea id="prompt" class="form-control" @bind="prompt" rows="3"
placeholder="生成したい画像の説明を入力してください"></textarea>
</div>
<div class="form-group mt-2 mb-4">
<button class="btn btn-primary" @onclick="GenerateImage" disabled="@isGenerating">
@if (isGenerating) { <span>生成中...</span> }
else { <span>画像を生成</span> }
</button>
</div>
</div>
<div class="col-md-6">
@if ( !string.IsNullOrEmpty(imageUrl) )
{
<div class="text-center">
<img src="@imageUrl" class="img-fluid rounded" style="max-width:100%;" />
</div>
}
</div>
</div>
@code {
}
先頭の@pageアノテーションで、このコンポーネントのURLを、/generateとして定義しています。
画面のレイアウトとしては、Bootstrapのグリッドシステムを利用して、左右に分割した構造にしています。左側には、プロンプト入力用のtextarea(テキストエリア)とボタンを配置しています。textareaでは、@bindディレクティブで、C#のprompt変数と連携させています。ボタンには、@onclickディレクティブでイベントハンドラを設定し、isGenerating変数に応じてボタンの文字を切り替えています。通常は「画像を生成」で、画像生成中は「生成中...」になります。
右側は画像のエリアです。imageUrl変数に値がある場合のみ、生成された画像を<img>タグで表示します。
画像生成して表示するロジックの追加
このコンポーネントのC#コード部分は、次のようにします。
@code {
private string prompt = ""; // プロンプト文
private string imageUrl = ""; // 生成画像のURL
private bool isGenerating = false; // 生成中を示すフラグ
private async Task GenerateImage()
{
// 入力がない場合は何もしない
if (string.IsNullOrWhiteSpace(prompt)) return;
isGenerating = true;
try
{
// 後で追加
}
finally { isGenerating = false; }
}
}
このページでは、テキストエリアでプロンプト(画像の説明)を入力し、ボタンクリックで画像生成を行います。ここでは一旦、画像生成の処理を空にしていますが、この後新規作成するサービスを利用する形にします。
画像生成ページのメニュー追加
次に、このページにアクセスできるようにナビゲーションメニューを更新します。LayoutフォルダのNavMenu.razorを開き、次のようにメニュー項目を追加します。
<div class="nav-scrollable" onclick="document.querySelector('.navbar-toggler').click()">
<nav class="flex-column">
~中略~
<div class="nav-item px-3">
<NavLink class="nav-link" href="generate">
<span aria-hidden="true"></span> 画像生成
</NavLink>
</div>
</nav>
</div>
画像生成を選択すれば、/generateとして定義されたページが表示されます。
