Algorithm & UI/UX
Canvas座標変換と動的スケーリングによる「高品質バナー生成」の自動化
本ツールでは、サーバーを介さずブラウザ上のCanvas 2D APIのみを用いて、高解像度な画像合成を行っています。単なる文字の描画にとどまらず、画像解像度に依存しない「見た目の等価性」を担保するためのアルゴリズムについて解説します。
1. 画像解像度に依存しない動的タイポグラフィ計算
ユーザーがアップロードする画像は、数百万画素のスマホ写真からウェブ用の小さな画像まで様々です。これらに対して一律のピクセル数でフォントサイズを指定すると、高解像度画像では文字が極小になり、低解像度では巨大化してしまいます。
本実装では、描画対象となるCanvasの width および height を基準とした「相対的な比率」を用いて、フォントサイズ、帯の高さ、さらにはドロップシャドウのボケ足までを動的に算出しています。
// 解像度に基づいた相対的な文字サイズの算出ロジック
function calculateCanvasMetrics(canvas, hasSubText) {
const w = canvas.width;
const h = canvas.height;
// 画像の短辺または長辺に基づいたベースサイズを決定(独自の計算比率)
const baseScale = Math.min(w, h) * // 独自のチューニング係数;
return {
mainFontSize: Math.floor(baseScale),
subFontSize: Math.floor(baseScale * // 独自のサブテキスト比率),
shadowBlur: Math.max(4, Math.floor(w * // 独自の影の拡散係数)),
bandHeight: hasSubText ? Math.floor(h * // 2行時の比率) : Math.floor(h * // 1行時の比率)
};
}
2. コンテキスト座標変換を用いた「左上リボン」描画アルゴリズム
「送料無料」などの文字を左上に斜めに配置する処理は、単純な座標指定では困難です。本ツールでは、Canvasの translate(平行移動)と rotate(回転)を組み合わせることで、数学的な複雑さを隠蔽しつつ柔軟なレイアウトを実現しています。
具体的には、描画の原点をリボンの中心予定地に移動させ、そこを軸に回転させることで、常に「水平な長方形」を描くコードのままで斜めの配置を可能にしています。
// 座標変換を用いたリボン描画のコア・コンセプト
function drawRibbonLayout(ctx, canvasWidth, canvasHeight) {
ctx.save();
// 1. 原点を配置位置(左上付近)に移動
ctx.translate(canvasWidth * // 横方向オフセット, canvasHeight * // 縦方向オフセット);
// 2. 指定の角度(例:-45度)で回転
ctx.rotate(-Math.PI / 4);
// 3. 原点を中心として帯とテキストを描画(0, 0 を中心に描画可能)
// ここに塗りつぶしとテキスト充填のロジックが入ります
ctx.restore(); // 座標系をリセット
}
3. heic2any によるクライアントサイドHEIC自動変換
iPhoneで撮影された写真はHEIC形式であることが多く、そのままではHTMLの <canvas> や <img> で扱うことができません。本ツールでは、heic2any ライブラリを dynamic import することで、必要時のみリソースをロードし、ユーザーの端末内で即座にJPEGへ変換しています。
これにより、プライバシーを守るために「外部サーバーに送信しない」という制約を維持したまま、iPhoneユーザーの利便性を最大化しています。
// HEIC形式の動的検知とクライアントサイド変換
async function processHeicImage(file) {
if (file.name.toLowerCase().endsWith('.heic')) {
const heic2any = (await import('heic2any')).default;
// サーバーに送らず、ブラウザのメモリ内で変換処理を実行
const convertedBlob = await heic2any({
blob: file,
toType: "image/jpeg",
quality: // 独自の圧縮品質設定
});
return Array.isArray(convertedBlob) ? convertedBlob[0] : convertedBlob;
}
return file;
}
Developer's Note
このツールを開発する上で最もこだわったのは、「直感的な操作感」と「プロの仕上がり」の両立です。フリマ出品はスピードが命。ユーザーが数値を入力するのではなく、画像サイズを自動解析して最適なバランスを提案する「お節介なほどの自動化」を内部で行っています。
また、Canvasでの描画は一度解像度を落としてしまうと二度と戻せません。プレビューは軽量なCanvasで、最終書き出しはオリジナルの解像度を維持したフルサイズCanvasで、という二段階のレンダリングパイプラインを構築することで、画質を一切妥協しない仕様にしました。