猫の手ツール

Algorithm & UI/UX

デジカメ特有の「光のにじみ」をCanvasで表現する

本稿では、2000年代のオールドデジカメが持つ「日付刻印」の独特なニュアンスを、ブラウザ上でいかに再現したか。その核となる画像処理と最適化のロジックをプロの視点で解説します。

1. 「2層描画」によるグロー効果の再現

デジカメの日付スタンプは単なるテキストの合成ではなく、LEDや液晶の発光が周囲にわずかに漏れる「にじみ(Bloom効果)」が特徴です。

Canvasの shadowBlur だけでは文字全体がボケて視認性が低下するため、本ツールでは「光彩レイヤー」と「輪郭レイヤー」を重ね合わせる手法を採用しています。

// 発光を再現する2ステップ描画
function renderText(ctx, text, x, y) {
    // 1層目:周囲への光の漏れ(にじみ)を表現
    ctx.shadowColor = '// 独自のオレンジ色設定';
    ctx.shadowBlur = // 独自のチューニング値;
    ctx.fillStyle = '// 透過を含むベースカラー';
    ctx.fillText(text, x, y);

    // 2層目:中心部の発光体をくっきりと上書き
    ctx.shadowBlur = 0; // 光彩をリセット
    ctx.fillStyle = '// 核心となる発光色';
    ctx.fillText(text, x, y);
}

この「あえて2回書く」という実装により、デジタルのシャープさとアナログの温かみを両立させています。

2. メモリ破綻を防ぐセーフティ・スケーリング

モバイルブラウザ、特にiOS Safariでは高解像度画像をCanvasで扱うとメモリ制限によりクラッシュするリスクがあります。

本ツールでは、読み込み時にアスペクト比を維持したまま、端末が安定して処理できる限界値まで動的にリサイズするロジックを組み込んでいます。

// メモリ消費を抑える解像度最適化
async function optimizeImage(img) {
    const LIMIT = // 端末負荷を考慮した最大閾値;
    let { width: w, height: h } = img;

    if (w > LIMIT || h > LIMIT) {
        const ratio = LIMIT / Math.max(w, h);
        // ここで再サンプリングの計算処理が入ります
        w = Math.floor(w * ratio);
        h = Math.floor(h * ratio);
    }
    
    // オフスクリーンCanvasを用いて高速にダウンサンプリング
    // ※ ユーザーの待機時間を最小化するための工夫
}

Developer's Note

開発にあたって最も苦労したのは、直感的な「ドラッグ操作」の精度です。

Canvasの物理解像度とブラウザ上の表示サイズが異なるため、単純なマウスクリック座標では位置がズレてしまいます。これを解決するために、座標変換用のマッピング関数を実装し、さらに「指で日付が隠れないように、ヒット判定エリアを少し上にずらす」といったUXの微調整を重ねました。