ガイド 第21

HUD/chrome システム

grid/grain/watermark/corner/frame

@event/visuals

VisualChrome@event/visuals)は xdeal の XdealChrome を 1 つの汎用プリミティブに一般化した背景レイヤ群である。全レイヤが var(--vis-*)brandCssVars の出力)を読むインラインスタイルなので、ブランドを差し替えるだけで色・書体・グレイン・透かしが一括で変わる。

レイヤ構成

1 枚の inset: 0 / pointer-events: none コンテナに、下から順に:

  1. faint grid — 2 本の linear-gradient(var(--vis-hair-soft) 1px, ...)64*u セルで敷く(opacity 0.5
  2. 巨大 italic 透かしグリフbrand.watermark。サイズ min(w,h)0.62scaleglyph が空文字なら描かない
  3. grainvar(--vis-grain) を 160×160 タイル、opacity 0.05
  4. inner frameinset: 26*u1px solid var(--vis-hair-soft) の枠
  5. 4 隅コーナー46u の L 字ブラケット(var(--vis-hair) 2px)を 36u オフセットに

全寸法は unit(w,h)(短辺 1080 = 1.0)から出すため、square でも banner でも比率非依存で崩れない。

brandCssVars を container 自身に注入する意味

<div style={{ ...brandCssVars(brand), position: "absolute", inset: 0, pointerEvents: "none" }}>
  {/* grid / watermark / grain / frame / corners は全て var(--vis-*) で描く */}
</div>

chrome コンテナが --vis-* を宣言するので、同じ root にコンテンツを重ねれば本文も同じトークンを継承する。カード側の使い方は「position: relative な root の先頭に <VisualChrome> を置き、その上にコンテンツを z-index で重ねる」。

props(レイヤの on/off と透かし位置)

type VisualChromeProps = {
  w: number; h: number; brand: EventBrand;
  grid?: boolean;        // 既定 true
  grain?: boolean;       // 既定 true
  corners?: boolean;     // inner frame + 4 隅(既定 true)
  watermark?: boolean;   // 既定 true(ただし glyph 空なら自動で描かない)
  watermarkScale?: number;   // 短辺比の倍率(会場パネルで大きく見せる時に上げる)
  watermarkRight?: number;   // 右オフセット(透かしサイズ比、正で内側へ)
  watermarkBottom?: number;
};

scanlines / rail は「意図的に非移植」

目次見出しは grid/grain/scanlines/corner/rail/watermark と superset で書いてあるが、出荷プリミティブに scanlines と rail は含まない:

  • VerticalRail — xdeal 固有の縦組みラベル(イベント名を縦に流す装飾)。イベント依存が強いので汎用 chrome には移植せず、必要なイベントが独自レイヤとして足す
  • scanlines — CRT 風の走査線。追加したいイベントは VisualChrome の上(または grain と同格)に repeating-linear-gradient を 1 枚重ねるだけで足せる。基底プリミティブを薄く保つため既定では入れていない

「基底 chrome は最小・装飾はイベント側で追加」が方針。追加レイヤも インラインスタイルのみにすれば capture(modern-screenshot / foreignObject = ブラウザ自身のレンダラ)で画面と完全一致で焼ける。CSS Module を使うと裏レンダの capture 時にスタイルが当たらず崩れるため、chrome は一貫してインラインで書いている。