Canvas Graphics & Memory Optimization
選挙ポスターの「記号性」を
ブラウザCanvasで動的に構築する
本ツールは、アップロードされた人物写真に対し、選挙ポスター特有のパーツ(タスキ、党名ボックス、名前)を、ユーザーの操作に合わせてリアルタイムにCanvas上で再構成します。今回は、その「デザインの動的合成」と「メモリ安全性の確保」について掘り下げます。
1. コンテクストの状態を分離した「タスキ」の幾何学的描画
選挙ポスターの象徴である「斜めのタスキ」は、静止画を載せるのではなく、Canvas APIの座標系を操作して描画しています。
単に矩形を描画するのではなく、save() と restore() を駆使して座標系を一時的に回転・スケールさせることで、他パーツ(写真や文字エリア)の描画ロジックに影響を与えずに、独立した角度(-35度など)でタスキを配置しています。
// タスキパーツの独立レンダリング
function renderSash(ctx, config) {
ctx.save();
// 1. 座標系の中心を移動
ctx.translate(CENTER_X + config.offsetX, CENTER_Y + config.offsetY);
// 2. 選挙ポスター特有の角度に回転
ctx.rotate( // 独自のチューニング角度 );
// 独自のスケール適用
const scale = config.size / 100;
ctx.scale(scale, scale);
// タスキの本体(塗り・線)とテキストを描画
// ここに矩形とfillTextによる合成処理が入ります
ctx.restore(); // 他の描画に影響が出ないよう即座に復帰
} この実装のメリットは、タスキの「大きさ」や「位置」をスライダーで変更しても、計算が非常にシンプルに済む点です。常に自身のローカルな座標軸で描画されるため、斜めの線に対する複雑な幾何学計算を排除し、パフォーマンスを稼いでいます。
2. モバイル端末を守る「階層型ダウンサンプリング」
近年の高画質写真は数千万画素に及びますが、そのままCanvasに展開すると、iOS Safari等のモバイル環境では利用可能なメモリ上限を超え、即座にクラッシュします。
本ツールでは、読み込み時に画像の長辺をチェックし、一定の閾値(セーフティガード)を超える場合は、描画用の適正サイズへ強制的にリサンプリングする処理を挟んでいます。
// 実行環境のメモリ負荷を考慮した初期リサイズ
i.onload = () => {
const MAX_DIMENSION = // 独自のセーフティ閾値;
let w = i.width;
let h = i.height;
if (w > MAX_DIMENSION || h > MAX_DIMENSION) {
const ratio = // アスペクト比を維持する係数計算;
w = Math.floor(w * ratio);
h = Math.floor(h * ratio);
// 内部Canvasを用いて一度だけ低解像度化(メモリの解放を狙う)
// ここにリサイズ用Canvasの描画とDataURL化の処理が入ります
}
// 処理済みの画像(img)を以降のレンダリングループで使用
};
一度リサンプリングしてから描画ループ(render())に渡すことで、ユーザーがドラッグ操作を行う際の負荷を軽減し、ヌルヌルとした操作感を実現しています。
3. 汎用性を高める「文字配置の条件分岐」と縦書き処理
ポスターの種類によって「名前を下に大きく入れる」「左に縦書きする」といったニーズに応えるため、Canvasの textAlign とループ処理を組み合わせて動的にレイアウトを切り替えています。
特に縦書き(left/right配置)では、Canvasの標準機能に縦書きが存在しないため、一文字ずつループで回し、フォントサイズに基づいたY座標のインクリメントによって擬似的に縦書きを再現しています。
Developer's Note
「いかに本物っぽく見せるか」にこだわり、タスキの lineWidth や党名の背景矩形の比率など、選挙ポスターのデザインガイドラインを意識したマジックナンバーを調整しました。
また、HEIC形式(iPhone標準の画像形式)への対応もエンジニアとして重要なポイントでした。ブラウザ標準では扱えないこの形式を、heic2any ライブラリを用いてフロントエンドのみで変換することで、サーバー送信なし(プライバシー保護)という本ツールの強みを守りつつ、iPhoneユーザーの利便性を最大化しています。