Algorithm & UI/UX
CanvasによるRPGステータス画面の動的生成技術
ブラウザ上での画像編集を滑らかにするため、本ツールではCanvas 2D APIを駆使した独自のレンダリング・アルゴリズムを採用しています。サーバーを一切介さないプライバシー重視の設計と、自由度の高い操作性を両立した実装の工夫を解説します。
このツールの入力から出力まで
現行コードの確認日:
- 入力
- 写真に加え、名前・数値・ステータスの文字を入力します。
- 処理
- ゲーム画面風の枠、ゲージ、文字を写真と合成します。
- 出力
- 長辺 1500px 以下の入力写真を使い、1200×800px の JPEG(品質指定 0.95)を保存します。
まず確認する点:写真から能力値を推定する機能ではありません。入力した数字とゲージの表現、長い名前の収まりを確認します。
仕上がりの例
猫の写真と名前を、RPGのステータス画面風にした例です。
名前やステータスの数値はサンプルです。
掲載画像はサイトにある既存の公開作例です。保存済みの資料では運営者の愛猫の写真を使用しています。今回の確認日が、この作例を実行した日を表すわけではありません。
保存済み検証記録の条件を見る
資料の種類は「ツールの出力画像を保存した記録」です。公開作例と保存済み記録で素材や色などが異なる場合があるため、下の数値は保存済み検証記録の条件として読んでください。
- 記録の入力画像
- 800×751px (JPEG)
- 記録の出力画像
- 1200×800px (JPEG)
| 画面の項目 | 記録の値 | 現行コードの初期値・範囲 |
|---|---|---|
| なまえ | ねこ | 初期値 タナカ |
| しょくぎょう | 日なたの番人 | 初期値 勇者 |
| Lv | 50 | 初期値 50 |
| HP | 250 | 初期値 250 |
| MP | 80 | 初期値 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 を変えてもバーの長さは変わらない実装です。
文字サイズは項目ごとに固定で、自動折り返しや長文の縮小はありません。長い名前や職業が右端や別項目に重ならないか、保存前に確認してください。
