猫の手ツール

Algorithm & UI/UX

Canvasで再現する「テレビ番組風」テロップの多重縁取りと座標変換

ブラウザ上で「バラエティ番組のような派手な縁取り」をどう実現するか。単なる文字入れツールを超えた、Canvas 2D APIの使いこなしとレスポンシブ対応の勘所を解説します。

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

現行コードの確認日:

入力
写真とテロップ文字、色や位置を入力します。
処理
文字の塗りと太い輪郭、影を順番に重ね、テレビ風の見た目をCanvasへ描きます。
出力
出力は長辺最大 1500px の JPEG(品質指定 0.95)です。

まず確認する点:長い文を枠内へ収める条件と文字の太さは別です。明るい写真でも輪郭が読めるか確認します。

仕上がりの例

写真に赤い帯と白い文字のテロップを加えた例です。

加工前・加工後
左は緑のかぶりものを着けた愛猫の写真。右は写真の右下に速報風の赤いテロップを加えた画像。

加工前・加工後

左は緑のかぶりものを着けた愛猫の写真。右は写真の右下に速報風の赤いテロップを加えた画像。

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

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

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

記録の入力画像
800×1066px (JPEG)
記録の出力画像
800×1066px (JPEG)
保存済み記録の主な操作・出力条件
画面の項目記録の値現行コードの初期値・範囲
記録で選択されていた項目ニュース速報風—
テロップを入力速報:本日の昼寝場所が 決まりました初期値 空欄
文字サイズ42初期値 読込前のHTML定義は40。読込後は画像の長辺×0.04を切り捨て(最低20) / 範囲 最小10。読込前の最大150。読込後の最大は画像の長辺×0.2を切り捨て(最低150)

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

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

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

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

1. Canvasにおける「多重縁取り」のレンダリング・アルゴリズム

バラエティ番組のような視認性の高いテロップを再現するため、本ツールではCanvasの strokeText を重ね書きする手法を採用しています。

Canvas標準の機能では一度に1つの縁取りしか設定できませんが、太い枠から順に描画し、最後に塗り(fillText)を重ねることで、多重の縁取りを実現しています。この際、lineJoin = 'round' を設定することで、文字の角が尖らずに滑らかなテレビ風の質感を表現しています。

バラエティ風の描画順です。ctx の font、文字位置の基準は呼び出し前に設定します。

function varietyText(ctx, text, x, y, fontSize) {
  ctx.lineJoin = 'round';
  ctx.lineWidth = fontSize * 0.4;
  ctx.strokeStyle = '#fff'; ctx.strokeText(text, x, y);
  ctx.lineWidth = fontSize * 0.15;
  ctx.strokeStyle = '#1e293b'; ctx.strokeText(text, x, y);
  ctx.fillStyle = '#fde047'; ctx.fillText(text, x, y);
}

2. 解像度依存を排除する座標同期スケーリング

このツールはレスポンシブ対応のため、CanvasをCSSで伸縮させています。しかし、ドラッグ操作でテロップを動かす際、マウスの座標(表示サイズ)とCanvas内部のピクセル座標(論理サイズ)が一致しないという問題が生じます。

これを解決するため、getBoundingClientRect() から算出される「表示上の比率」を常に計算し、座標を正規化するアルゴリズムを組み込みました。これにより、PCでもスマホでも、触った場所をそのまま動かせる直感的なUXを提供しています。

3. 端末内完結を実現する動的リサイズとHEIC処理

「プライバシー重視」を掲げる本ツールでは、すべての処理をブラウザ内で完結させる必要があります。特にiPhoneのHEIC形式への対応と、メモリ不足によるクラッシュ防止が課題でした。

巨大な画像が読み込まれた場合、アスペクト比を維持しながら MAX_SIZE (長辺 1500px)に自動縮小するロジックを実装しています。オフスクリーンCanvasを用いて再描画することで、処理に使う画素数を減らし、後続のテロップ合成処理のパフォーマンスを最適化しています。

出力の仕様と確認する点

ニュース風は赤い帯と白文字、バラエティ風は白縁・黒縁・黄色文字、YouTube 風は影・赤縁・白文字、ドキュメンタリー風は明朝体で描きます。表示スタイルを選び、画像内で読みやすい位置にドラッグします。

文字は手動改行でき、行間はサイズの 1.3 倍です。横幅の自動縮小や折り返しはないため、長い文章は小さくするか改行します。帯の幅は最長行を測って決まります。

出力は長辺最大 1500px の JPEG(品質指定 0.95)です。動画用の字幕トラックではなく、1枚の写真に文字を合成します。フォントは端末で利用可能なものから選ばれるため字形が異なる場合があります。