📝 はじめに
R3FのCanvasを使うと、通常のDOMだけでは作りにくい奥行きや立体感をセクション背景に足せます。
ただし、背景を作るために見出しや本文までCanvas内に入れてしまうと、テキスト選択、リンク、アクセシビリティ、レスポンシブ調整が扱いにくくなります。この記事では、R3Fは3D表現、HTMLは情報表示という責務分離を主役にして、1つのセクション内でCanvasを背面に敷く最小構成を作ります。
今回はこれ以外: shader、画像テクスチャ、マウス追従、ScrollTrigger、完成されたHero演出
今回の主役: R3F CanvasをDOM背景として配置する基本構造
最小単位: 1つのセクション内で、背面にCanvas、前面にHTMLテキストを重ねるだけ
差分: 背景表現を作り込むのではなく、レイヤー構造と責務分離だけに絞る
再利用先: Hero背景、導入セクション、CTA前の区切り、記事詳細の見出し背景
分離する責務: R3F / WebGLは背景の3D表現、DOMはテキストとリンク、CSSは重なり順と余白
🎯 今回作るもの
作るのは、1つのセクションの背面にR3FのCanvasを置き、その上に通常のHTMLテキストを重ねる小さな部品です。
- 主役: R3F Canvasを背景レイヤーとして配置する構造
- トリガー: 初回表示後の常時描画
- 対象要素: 背景Canvas、前面のHTML見出しと本文
- 再利用先: Hero背景、セクション背景、キャンペーン導入、記事ページのキービジュアル
ここでは3Dオブジェクトの完成度を上げることは目的にしません。背景には簡単なtorusKnotGeometryを1つ置くだけにして、読み手が「どこがCanvasで、どこがHTMLか」を追いやすい構成にしています。
🧩 コンポーネント設計
このデモは、3つの役割に分けます。
-
Demo セクション全体を持つ親コンポーネントです。背景Canvasと前面DOMを並べるだけにして、細かいWebGL処理は直接書きません。
-
CanvasBackground Canvasを包む背景レイヤーです。
aria-hidden="true"を付けて、装飾背景として扱います。ここにカメラ、ライト、背景色をまとめます。 -
BackgroundShape Canvas内の3Dオブジェクトだけを担当します。
useFrameで少しだけ回転させますが、DOMやCSSのことは知りません。
HTMLテキストをCanvas内に入れない理由は、情報表示としての扱いやすさを保つためです。見出しや本文、リンクは通常のDOMにしておくと、フォント、行間、折り返し、リンクのクリック、SEO、スクリーンリーダー対応をいつものCSSとHTMLの流れで調整できます。
🛠️ 実装のポイント
sectionにはposition: relativeを付けます。これは、内側のCanvasレイヤーをposition: absoluteで配置するときの基準を作るためです。
背景レイヤーにはposition: absolute、inset: 0、z-index: 0を指定します。inset: 0でセクション全体を覆い、z-index: 0で前面DOMより後ろに置きます。Canvasはこのレイヤーの中だけで描画されるので、セクション背景として扱いやすくなります。
前面の.r3f-contentにはposition: relativeとz-index: 1を付けます。z-indexは、同じ重なり文脈の中でどちらを手前に出すかを決めるための指定です。CanvasとHTMLが同じ場所に重なる場合、前面コンテンツ側にも明示的なz-indexを持たせると、後から背景の要素を増やしても表示順が崩れにくくなります。
.r3f-sectionのisolation: isolateは、このセクション内の重なりを外側の要素から切り離すための保険です。ページ全体のヘッダーや他セクションに大きなz-indexがある場合でも、この部品内のz-index: 0とz-index: 1の関係を読みやすくできます。
pointer-events: noneは、背景Canvasがクリックやhoverを受け取らないようにするための指定です。今回のCanvasは装飾背景なので、前面のリンクやボタンの操作を邪魔しないことが大切です。逆に、Canvas側でマウス操作を受けたいデモでは、この指定を外してCanvas側にイベント処理を持たせます。
R3F側は3D表現だけに絞ります。Canvasは描画面、BackgroundShapeは簡単なメッシュ、useFrameは背景にわずかな動きを与える処理です。前面テキストの余白や読みやすさはCSSで決めるので、Canvas内にHTMLレイアウトの責務を混ぜません。
🔧 使いどころとカスタマイズ
実務では、Hero背景やセクション背景にそのまま転用しやすい粒度です。ページ全体の演出として作り込む前に、この構造を1つのセクションで安定させると、後から背景だけ差し替えやすくなります。
調整ダイヤルは、次の値から触ると印象を変えやすいです。
- セクションの高さ:
.r3f-sectionのmin-height。Hero寄りなら560px以上、記事中の区切りなら320px前後。 - Canvasの前後関係:
.r3f-background-layerのz-index: 0と.r3f-contentのz-index: 1。背景と本文の順序を固定するための基本セット。 - 操作の受け渡し:
.r3f-background-layerのpointer-events。装飾背景ならnone、Canvas操作が必要ならauto。 - 3Dの存在感:
SCENE_CONFIG.meshColor、BackgroundShapeのscale、ライトのintensity。本文より目立ちすぎる場合は、スケールやライトを下げます。 - 動きの強さ:
SCENE_CONFIG.rotationSpeed。背景用途では0.1〜0.25程度に抑えると、前面の文章を読む邪魔になりにくいです。 - 画質と負荷:
Canvasのdpr={[1, 1.5]}。高精細にしすぎると負荷が上がるので、背景では上限を控えめにします。
Canvasを背景に分けると、HTML側の文章量が増えても3Dシーンを直さずに済みます。反対に、背景のメッシュやライトを変更しても、前面DOMの情報設計には触れずに済みます。この分離が、実務で使い回しやすい一番の理由です。
🚀 発展させるなら
次に発展させるなら、まずは背景オブジェクトの種類を変える程度に留めるのがおすすめです。sphereGeometryやicosahedronGeometryに差し替えるだけでも、セクションの印象は変わります。
その後で、画面幅に応じてメッシュ位置を変える、Canvasの背景色をテーマ変数に合わせる、前面DOMにCTAを足す、といった順番で拡張します。shader、画像テクスチャ、マウス追従、スクロール連動は魅力的ですが、まずはCanvasが背景として安全に配置されていることを確認してから足す方が、構造が崩れにくくなります。
_animation-inventory.md に追記する台帳メモ
r3f-canvas-background-basic
- 主役: Canvas背景
- 軸: R3F CanvasをDOMコンテンツの背面レイヤーとして配置する
- トリガー: 初回表示後の常時描画
- 見せ場: 1つのセクション内でCanvas背景とHTML本文を重ねる構造
- 次回避ける: 背景Canvasと前面DOMのz-index / pointer-events整理だけを主役にする構成