猫の手ツール

Algorithm & UI/UX

Canvasで実現する「プロ風」デザインの自動化とリソース最適化

画像加工ツールにおける最大の課題は、ユーザーがアップロードする「未知の解像度」と「多様なファイル形式」への対応、そしてブラウザの「メモリ制限」です。本ツールでは、iPhoneのHEIC形式への対応から、Canvasを用いた動的なタイポグラフィ計算まで、すべてをクライアントサイドで完結させています。

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

現行コードの確認日:

入力
写真と見出しなどの文字を入力し、テンプレートを選びます。
処理
Canvasで背景写真と帯・文字を重ね、固定の出力枠へ合成します。
出力
出力は OGP 用が 1200×630px、16:9 が 1280×720px の JPEG(品質指定 0.85)です。

まず確認する点:長い見出しの収まりと写真上の文字のコントラストを確認します。生成した画像を掲載先で縮小して見たときの読みやすさも確かめます。

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

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

1. モバイル安定化のためのプリ・リサイジング・ハック

高画質なカメラで撮影された写真は、1枚で数十MB、解像度が5000pxを超えることも珍しくありません。これらをそのままCanvasで処理しようとすると、特にiOSのブラウザではメモリ不足でクラッシュしてしまいます。本ツールでは、編集開始前に隠しCanvasを用いて「実装で定めた長辺 2000px 以下」へダウンサンプリングを行っています。

メリット: 読み込み後の処理画像を小さくします。プレビューの Canvas 自体は保存と同じ規定寸法を使う実装で、速度の改善量を保証するものではありません。

主タイトルの行数とサブタイトルの有無から最初の行の位置を求める例です。

function titleStartY(height, lineCount, hasSubtitle) {
  const mainSize = Math.floor(height * 0.12);
  const subSize = Math.floor(height * 0.05);
  const total = mainSize * 1.3 * lineCount + (hasSubtitle ? subSize * 2 : 0);
  return height / 2 - total / 2 + mainSize / 2;
}

2. 動的タイポグラフィ:多行テキストの中央揃えアルゴリズム

ユーザーが入力したタイトルを単に中央に描画するだけでは、改行が含まれた際にバランスが崩れます。本ツールでは、テキストを配列化し、フォントサイズと行間、さらには任意で入力されるサブタイトルの領域をすべて合算した「仮想的なバウンディングボックス」を計算してから描画を開始します。

メリット: 行数とサブタイトルの有無に応じて、文字全体の中心を画像中央へ合わせます。ただし高さの上限に収まるよう自動縮小する処理はありません。

3. iPhoneユーザーに寄り添うHEIC変換とUX

HEIC形式の写真は、画像を外部 API へ送らず、必要な時だけライブラリを動的インポート(Dynamic Import)して処理します。

メリット: 初期ロード時のJSサイズを最小限に抑えつつ、iPhoneで撮った写真をそのまま加工したいというユーザーのニーズを、プライバシーを損なうことなく(サーバーに送らずに)満たせます。

出力の仕様と確認する点

背景写真は中央を基準に出力枠いっぱいへ拡大し、はみ出す部分を切り取ります。人物の位置を認識する処理や手動ドラッグによる構図調整はありません。見せたい対象を中央に置いた写真が向きます。

主タイトルは高さの 12%、サブタイトルは 5% の固定比率です。主タイトルの各行は幅 90% を上限として描きますが、サブタイトルは幅制限がないため、長い文字列は画像端からはみ出す場合があります。

出力は OGP 用が 1200×630px、16:9 が 1280×720px の JPEG(品質指定 0.85)です。全体を暗くする・中央帯・上下のシネマ帯で背景と文字を分けます。行数が多い場合は主タイトルを短くし、端まで読めるか保存画像を確認します。