猫の手ツール

Algorithm & UI/UX

CanvasによるRPGステータス画面の動的生成技術

ブラウザ上での画像編集を滑らかにするため、本ツールではCanvas 2D APIを駆使した独自のレンダリング・アルゴリズムを採用しています。サーバーを一切介さないプライバシー重視の設計と、自由度の高い操作性を両立した実装の工夫を解説します。

このツールの入力から出力まで

現行コードの確認日:

入力
写真に加え、名前・数値・ステータスの文字を入力します。
処理
ゲーム画面風の枠、ゲージ、文字を写真と合成します。
出力
長辺 1500px 以下の入力写真を使い、1200×800px の JPEG(品質指定 0.95)を保存します。

まず確認する点:写真から能力値を推定する機能ではありません。入力した数字とゲージの表現、長い名前の収まりを確認します。

仕上がりの例

猫の写真と名前を、RPGのステータス画面風にした例です。

加工前・加工後
左は横になった愛猫の写真。右は猫の写真、名前、HP・MPのゲージを配置したステータス画像。

名前やステータスの数値はサンプルです。

加工前・加工後

左は横になった愛猫の写真。右は猫の写真、名前、HP・MPのゲージを配置したステータス画像。

掲載画像はサイトにある既存の公開作例です。保存済みの資料では運営者の愛猫の写真を使用しています。今回の確認日が、この作例を実行した日を表すわけではありません。

保存済み検証記録の条件を見る

資料の種類は「ツールの出力画像を保存した記録」です。公開作例と保存済み記録で素材や色などが異なる場合があるため、下の数値は保存済み検証記録の条件として読んでください。

記録の入力画像
800×751px (JPEG)
記録の出力画像
1200×800px (JPEG)
保存済み記録の主な操作・出力条件
画面の項目記録の値現行コードの初期値・範囲
なまえねこ初期値 タナカ
しょくぎょう日なたの番人初期値 勇者
Lv50初期値 50
HP250初期値 250
MP80初期値 80
ちから120初期値 120

記録では「このステータスを保存する」から完成表示へ進んでいます。初期値と記録値を比べてから、効果を1項目ずつ変えると作用を確認しやすくなります。

資料ファイルの作成日は実行日として扱っていません。個別端末の処理速度や、ほかの写真に対する検出・加工の精度を測定した資料でもありません。

実装の確認箇所:src/pages/image/rpg-status/index.astro。以下のコード抜粋と出力条件は、この本番実装に基づいて説明します。

仕組みを読み進めるときは、Canvas APIと画像処理(画像寸法、drawImage、画素と透明度の扱い)、File APIとObject URL(選んだ画像の読み込みとBlob URLの解放)が参考になります。

1. ポートレートの動的座標計算とクリッピング

ユーザーがアップロードした画像を「特定の枠(ポートレート枠)」の中に収めつつ、ドラッグやズームで自由に調整できる機能は、単純なCSSでは実現が難しい部分です。Canvasの clip() メソッドと、独自の座標変換ロジックを組み合わせることで、直感的な操作感を実現しています。

なぜこの実装なのか?

画像の絶対座標ではなく、枠の中心を基準とした相対的な変位を計算することで、ズーム時でも「見ている場所」がズレにくい安定した挙動を提供しています。また、描画の度にコンテキストの状態を保存・復元(save/restore)することで、他のUI要素(ステータスバーなど)にクリッピングの影響を与えない設計にしています。

現在の HP・MP バーは数値に比例せず、背景 450px に対して色部分を 380px で描く装飾です。その描画部分を示します。

function statusBar(ctx, x, y, color) {
  ctx.fillStyle = '#333';
  ctx.fillRect(x, y, 450, 15);
  ctx.fillStyle = color;
  ctx.fillRect(x, y, 380, 15);
}

2. メモリ消費を抑える「読み込み時リサイズ」ハック

近年のスマートフォンの写真は非常に高解像度であり、そのままCanvasで扱うとメモリ不足によるクラッシュや、レンダリングの遅延を招きます。本ツールでは、画像をメモリ上に読み込んだ瞬間に、内部処理に最適な解像度へ自動リサイズする前処理レイヤーを設けています。

なぜこの実装なのか?

最終的な出力品質を保ちつつ、編集中のフレームレート(FPS)を維持するためです。一度適切なサイズにダウンサンプリングされた 画像オブジェクトを使い回すことで、後続の描画で扱う画素数を減らします。

3. レイヤード・レンダリングによる即時プレビュー

名前や職業、各種パラメータが変更されるたびに、Canvas全体を再描画する「リアクティブな描画システム」を構築しています。フォントのレンダリングにおいて、視認性を高めるためのシャドウ処理や、固定長のステータスバー描画を一括で処理しています。

なぜこの実装なのか?

ゲームのような「リアルタイム感」を出すためには、入力値の変化を即座にCanvasへ反映させる必要があります。HTML要素を重ねるのではなく、すべてを一枚のCanvasに描くことで、最終的な「画像保存」時の同じ描画結果を画像として出力できます。

出力の仕様と確認する点

長辺 1500px 以下の入力写真を使い、1200×800px の JPEG(品質指定 0.95)を保存します。人物写真は枠内に切り抜いて描き、ドラッグと 50〜300% のズームで位置を合わせます。

名前、職業、レベル、HP・MP、ちから・まもり・はやさは入力文字を表示します。写真から能力を診断する機能ではありません。HP・MP を変えてもバーの長さは変わらない実装です。

文字サイズは項目ごとに固定で、自動折り返しや長文の縮小はありません。長い名前や職業が右端や別項目に重ならないか、保存前に確認してください。