1 デザインを複数サイズへ書き出すための寸法定義を、@event/visuals は データで持つ。3 アプリでは各所に手書きだった FORMATS / VENUE_FORMATS / isVenue 判定を 1 レジストリに統合した。
Format 型
type Format = {
id: string;
w: number; h: number; // 1× DOM 描画寸法(px)。書き出しは exportScale 倍
exportScale: number; // 出力ピクセル倍率。SNS=2 / A 系=3 / シール=4
pageMm?: [number, number]; // PDF/印刷の物理サイズ。未指定 = PDF 非対応(SNS)
label?: string; kind?: "sns" | "venue";
};
⚠ Format は asset-kit の ExportFmt({ w, h, exportScale, pageMm? })の 上位互換なので、exportPng / exportPdf に そのまま渡せる(id/label/kind の余剰フィールドは無視される)。
SNS マトリクス(印刷なし)
| id | 寸法 | 用途 |
|---|---|---|
square | 1080×1080 | 正方形 1:1 |
portrait | 1080×1350 | 縦長 4:5 |
stories | 1080×1920 | ストーリー 9:16 |
og | 1200×630 | OGP 1.91:1 |
全て exportScale: 2(Retina 相当)。
会場マトリクス(印刷 = pageMm 付き)
panelA1/panelA2/panelA3— 3 つとも同一キャンバス 1191×1684(A 比 1:√2)。違いはpageMmだけ(aSeriesMm(1|2|3))。exportScale: 3banner— 1080×3240(1:3)、pageMm: [600, 1800]のサイドバナーsticker— 612×612、exportScale: 4、pageMm: [51, 51](仕上り 45mm + 塗り足し 3mm)
A 系(ISO 216)の √2 math — なぜ 1 キャンバスで足りるか
A 系は縦横比が 1:√2 固定で、1 段大きくなるごとに面積 2 倍・辺長 √2 倍になる。
A_SERIES_RATIO = Math.SQRT2; // 1.414…
aSeriesMm(n) // → [floor(841/2^(n/2)), floor(1189/2^(n/2))]
// A1=594×841 / A2=420×594 / A3=297×420(ISO 実測に一致)
printScale(fromA, toA) = Math.pow(Math.SQRT2, fromA - toA);
// printScale(3, 2) = 1.414(A3 レイアウトを A2 印刷へ)
A3 で 1 度組めば、印刷時に pageMm を差し替えるだけで A2/A1 に拡大できる。 ベクター PDF は解像度非依存なので DOM の再レイアウトは不要。同一 1191×1684 キャンバスを A1 で刷れば ~150dpi、A3 なら ~300dpi に落ちる(exportScale: 3 の実ピクセルが効く)。DOM に直接拡大を効かせたい場合(ivs の Startup Market の --print-k)は printScale() の係数を CSS 変数へ流す。
レジストリと幾何ヘルパ
const reg = createFormatRegistry(); // 既定 = 全 FORMATS
reg.byId("square"); // Format | undefined
reg.byKind("venue"); // 会場フォーマットだけ
unit(w, h) // = min(w,h)/1080。短辺 1080 を 1.0 とするスケール単位(比率非依存でフォント/余白を出す)
isWide(w, h) // = w > h*1.15。横長レイアウトへ切替える判定
テンプレ/chrome は寸法を直書きせず unit(w,h) から出すため、square でも stories でも banner でも同じコードで崩れずに組める。starter のスタジオ(src/lib/visuals.ts)は SNS 4 種 + panelA3 + banner を STUDIO_FORMATS として選ばせている。