Algorithm & UI/UX
映画の「情緒」をCanvasで再現する:
動的タイポグラフィと描画最適化の裏側
「エモい」という感覚は、微細なバランスの積み重ねで生まれます。本ツールでは、Canvasの低レベルAPIを駆使し、どのような解像度の画像でも「映画的な黄金比」を維持するためのロジックを実装しています。
1. 視認性を極める「多重描画アルゴリズム」
映画の字幕において最も重要なのは、背景がいかなる色であっても文字がはっきりと読めることです。
本ツールでは、strokeText(外枠)と fillText(塗り)を組み合わせるだけでなく、外枠の太さをフォントサイズに比例して動的に算出(Dynamic Stroke Weight)しています。また、lineJoin = 'round' を適用することで、角の鋭利さを抑えた「フィルム上映」のような柔らかい質感を演出しています。
// 視認性と情緒を両立する描画ロジックの断片
ctx.font = `900 ${layout.mainFontSize}px ${fontFam}`;
ctx.textAlign = 'center';
ctx.lineJoin = 'round';
// フォントサイズに応じた動的なフチの太さ計算
ctx.lineWidth = Math.max(3, layout.mainFontSize * // 独自の比率係数);
ctx.strokeStyle = 'rgba(0, 0, 0, 0.85)'; // 透過度を微調整した黒
// 外枠と塗りを重ねることで、強いコントラストを生む
ctx.strokeText(line, x, y);
ctx.fillText(line, x, y); 2. 解像度に依存しない「黄金比スケール」
スマホの写真は、4Kクラスの高解像度から古い低解像度のものまで千差万別です。
フォントサイズを固定値にすると、高解像度画像では文字が豆粒のようになり、逆に低解像度では画面を埋め尽くしてしまいます。この問題を解決するため、画像の高さ(Height)を基準に「メイン字幕は5%」「サブ字幕は2.5%」といった比率計算を画像読み込み時に実行し、常に情緒的なバランスが保たれるようにしています。
// 画像の高さに基づいた動的サイズ算出
img.onload = () => {
const h = img.height;
// 画面全体に対して「映画的に美しく見える」比率でフォントサイズを決定
layout.mainFontSize = Math.max(20, Math.floor(h * // 独自のレイアウト定数));
layout.subFontSize = Math.max(12, Math.floor(h * // 独自のレイアウト定数));
// 字幕の初期位置も、シネマスコープ(黒帯)の幅を考慮して自動配置
layout.y = h - (h * // 独自の余白係数) - layout.mainFontSize;
renderCanvas();
}; 3. パフォーマンスと機能性を両立する「遅延インポート」
iPhoneで標準的なHEIC形式をブラウザで扱うには重量級の変換ライブラリが必要です。しかし、すべてのユーザーがHEICを使うわけではありません。
本ツールでは、ファイル読み込み時に拡張子を判定し、HEIC形式の場合のみ dynamic import を用いて heic2any モジュールを非同期でロードします。これにより、通常のJPG/PNG利用ユーザーの初期読み込み負荷(LCP)を最小限に抑えています。
// 必要な時だけ重い処理をロードする戦略
async function handleFile(file) {
if (file.name.toLowerCase().match(/\.(heic|heif)$/)) {
// ここで変換モジュールを動的インポート
// ここに非同期のデコード処理が入ります
const converted = await heicProcessor.convert(file);
processBlob = converted;
}
// 以降、標準的なCanvas描画フローへ
} Developer's Note
実装において最もこだわったのは、字幕の「ドラッグ操作」の滑らかさです。
Canvas上の要素はDOMではないため、そのままでは掴めません。そのため、マウスやタッチの座標をCanvas内部座標に変換し、字幕のバウンディングボックス内に収まっているかを判定する「簡易的な当たり判定エンジン」を自前で実装しました。
また、あえてフォントの種類を絞り、「明朝体(セリフ)」と「ゴシック体(サンセリフ)」の2択にしたのもこだわりです。選択肢を増やすことよりも、一発で「それっぽくなる」体験を提供することを優先しました。ぜひ、何気ない日常の写真を一枚、映画の終幕のような特別な風景に変えてみてください。