3Dフロントエンド — スクロール駆動の3Dウェブサイト
Three.jsを使用した3Dシーン内を、スクロールで歩き回ることができる没入型のシングルファイルHTMLページを作成します。見出し、テキスト、画像、CTAなどのコンテンツは、3Dワールドにオーバーレイまたは埋め込まれます。すべてのDreamWalkページは自己完結型の.htmlアーティファクトです。ビルドツール、npm、Reactは不要です。
技術スタック
すべての出力はシングルファイルHTMLアーティファクトです。ビルドツール、npm、Reactは不要で、自己完結した.htmlファイルのみで構成されます。
| ライブラリ | CDN | 目的 |
|---|---|---|
| Three.js r128 | https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js | 3Dレンダリングエンジン |
| GSAP 3.12.5 | https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js | アニメーションエンジン |
| ScrollTrigger 3.12.5 | https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js | スクロールとアニメーションのバインド |
なぜこのスタックか? Three.jsは最大のエコシステムを持つ支配的なWebGLフレームワークです。GSAP ScrollTriggerは、スクロール位置をアニメーションタイムラインにマッピングするための業界標準です。この組み合わせは、多くの受賞歴のある3Dスクロールウェブサイト(Awwwards、FWAを参照)を支えています。また、ビルドステップなしで単一のHTMLファイルで動作するため、アーティファクトに最適です。
重要: Three.js r128 APIの制約。 これは最新のThree.jsではありません。r128には以下は存在せず、絶対に使用してはいけません:
CapsuleGeometry、RoundedBoxGeometry、THREE.MathUtils.seededRandom、WebGPURenderer、THREE.ColorManagement。常にBufferGeometryプリミティブ(BoxBufferGeometry、SphereBufferGeometryなど)またはそのエイリアス(BoxGeometry、SphereGeometry)を使用してください。
アーキテクチャパターン
┌─────────────────────────────────────────┐
│ HTMLページ │
│ ┌───────────────────────────────────┐ │
│ │ <canvas> - Three.jsシーン (固定) │ │
│ │ • パス/スプライン上のカメラ │ │
│ │ • 3Dオブジェクト (ジオメトリ/パーティクル) │ │
│ │ • ライティングとフォグ │ │
│ └───────────────────────────────────┘ │
│ ┌───────────────────────────────────┐ │
│ │ <div class="scroll-container"> │ │
│ │ 高さ: 500vh+ (スクロール可能) │ │
│ │ テキスト/コンテンツを含むセクション │ │
│ │ position:fixedまたはスクロール │ │
│ │ トリガーで透明度フェードでオーバーレイ│ │
│ └───────────────────────────────────┘ │
│ │
│ GSAP ScrollTriggerがスクロール%を │
│ camera.position / camera.lookAt / │
│ オブジェクトのトランスフォーム / マテリアルパラメータにマッピング│
└─────────────────────────────────────────┘
3Dスクロールページの構築方法
コードを書く前に、references/PATTERNS.mdを読んで詳細なコピーペースト可能なコードパターンを確認してください。 カメラアニメーション、ライティング、シェーダー、パーティクル、プロシージャルジオメトリ、パフォーマンス最適化のための40以上のプロダクションレディなパターンが含まれています(すべてThree.js r128互換)。
ステップ1: シーンのデザイン
ユーザーの意図に基づいて体験タイプを決定します:
| タイプ | カメラの動作 | 最適な用途 |
|---|---|---|
| トンネル / コリドー | Z軸に沿って前方に飛ぶ | 製品の公開、ストーリーテリング |
| オービット / ショーケース | 中央のオブジェクトの周りを回転 | 製品ページ、ポートフォリオ |
| ランドスケープフライオーバー | 地形/都市景観の上をスイープ | ランディングページ、イントロ |
| ルームウォークスルー | 接続された空間を移動 | バーチャルツアー、プレゼンテーション |
| 垂直降下 | カメラがY軸に沿って下降 | タイムライン、レイヤーの公開 |
| スプラインパス | カメラが湾曲した3Dパスに沿って移動 | シネマティック、エディトリアル |
ステップ2: HTMLのスキャフォールディング
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Experience</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { overflow-x: hidden; }
canvas { position: fixed; top: 0; left: 0; z-index: 0; }
.scroll-container { position: relative; z-index: 1; pointer-events: none; }
.section { height: 100vh; display: flex; align-items: center; justify-content: center; }
.content { pointer-events: auto; /* インタラクティブ要素の場合再設定 */ }
</style>
</head>
<body>
<!-- Three.jsキャンバスはプログラムで作成されます -->
<div class="scroll-container">
<!-- セクションがスクロールの高さを決定; コンテンツは3Dシーンにオーバーレイ -->
<div class="section" id="section-1">...</div>
<div class="section" id="section-2">...</div>
<!-- セクションを追加する = スクロール距離が長くなる = カメラの移動距離が長くなる -->
</div>
<script src="THREE_CDN"></script>
<script src="GSAP_CDN"></script>
<script src="SCROLLTRIGGER_CDN"></script>
<script>
// シーンのセットアップ、アニメーション、ScrollTriggerのバインド
</script>
</body>
</html>
ステップ3: コアなThree.jsのセットアップ
常に以下の基本要素を含めてください:
- シーン + カメラ + レンダラー — 没入感を出すためにFOV 60-75の
PerspectiveCameraを使用 - ライティング — 最低でも: 1つの
AmbientLight+ 1つのDirectionalLight。演出のためにPointLightまたはSpotLightを追加 - フォグ —
scene.fog = new THREE.FogExp2(color, density)で奥行きを追加し、ポップインを隠蔽 - リサイズハンドラー — 常に
window.resizeを処理 - レンダリングループ —
requestAnimationFrameとrenderer.render(scene, camera)
ステップ4: GSAPによるスクロール→カメラアニメーション
重要なバインドパターン:
gsap.registerPlugin(ScrollTrigger);
// カメラアニメーションのターゲットをプレーンオブジェクトとして保存
const camAnim = { x: 0, y: 2, z: 10, lookX: 0, lookY: 0, lookZ: 0 };
const tl = gsap.timeline({
scrollTrigger: {
trigger: ".scroll-container",
start: "top top",
end: "bottom bottom",
scrub: 1, // 1秒のスムージング
}
});
// カメラキーフレームをチェーン
tl.to(camAnim, { x: 0, y: 2, z: 5, lookX: 0, lookY: 0, lookZ: 0, duration: 1 })
.to(camAnim, { x: 3, y: 1, z: 0, lookX: 2, lookY: 0, lookZ: -5, duration: 1 })
.to(camAnim, { x: 0, y: 5, z: -10, lookX: 0, lookY: 0, lookZ: -15, duration: 1 });
// レンダリングループ内でアニメーション値を適用
function animate() {
requestAnimationFrame(animate);
camera.position.set(camAnim.x, camAnim.y, camAnim.z);
camera.lookAt(camAnim.lookX, camAnim.lookY, camAnim.lookZ);
renderer.render(scene, camera);
}
ステップ5: コンテンツオーバーレイ
スクロール位置でフェードイン/アウトするHTMLコンテンツをオーバーレイします:
// カメラがウェイポイントに達したときにセクションをフェードイン
gsap.fromTo("#section-2 .content",
{ opacity: 0, y: 50 },
{ opacity: 1, y: 0,
scrollTrigger: {
trigger: "#section-2",
start: "top center",
end: "top 20%",
scrub: true
}
}
);
ステップ6: ビジュアルの洗練
これらを適用して、基本的なものから印象的なものへと昇華させます:
- パーティクル — 浮遊する埃/星のために
THREE.PointsとTHREE.BufferGeometryを使用 - ポストプロセッシンググロー — エミッシブマテリアルとブルーム風の明るい色を使用
- カラートランジション — スクロールに合わせて
scene.backgroundとscene.fog.colorをアニメーション - オブジェクトの出現 — カメラが近づくにつれてオブジェクトを0からスケールアップまたはフェードイン
- パララックスレイヤー — 異なる距離にあるオブジェクトを異なる速度で移動
- 微かな回転 — レンダリングループ内で装飾オブジェクトをゆっくり回転(スクロールとは独立)
- マウスパララックス — マウス位置に基づいてカメラをわずかにオフセットし、奥行き感を演出
デザイン原則
- パフォーマンス最優先 — ジオメトリはシンプルに。
BufferGeometryを使用し、ドローコールを制限し、fogで遠くのオブジェクトを隠す。60fpsを目標に - スムーズなスクロール — ScrollTriggerで
scrub: 1またはscrub: 2を使用し、滑らかな動きに。scrub: true(インスタントでカクつく)は絶対に使用しない - 読みやすいコンテンツ — テキストオーバーレイにはコントラストが必要。明るいテキストの背後に半透明の暗いパネルを使用するか、テキストエリアの背後で3D背景を暗く/ぼかす
- モバイルフォールバック — タッチスクロールはScrollTriggerで動作。
window.innerWidthチェックを使用して、モバイルではパーティクル数とジオメトリの複雑さを減らすことを検討 - グレースフルな読み込み — シンプルなCSSローディング画面を表示し、Three.jsシーンの準備ができたら非表示にする
よく使われる3Dオブジェクト(外部モデル不要)
これらはすべてThree.jsの組み込みジオメトリで作成可能 — GLTFファイルは不要:
- 浮遊する幾何学形状 — MeshStandardMaterialを適用したBoxGeometry、IcosahedronGeometry、TorusKnotGeometry
- 地形 — 頂点変位(サイン波、ノイズ)を適用したPlaneGeometry
- パーティクルフィールド — 星、埃、雪、データ可視化のためのBufferGeometry + Points
- グリッド床 — GridHelperまたはカスタムラインジオメトリ
- チューブ/トンネル — CatmullRomCurve3パスに沿ったTubeGeometry
- テキスト — PlaneGeometryにレンダリングされたキャンバステクスチャ、またはスプライトベース
- ワイヤーフレームオブジェクト — テクノロジー的な美学のために
wireframe: trueマテリアルを適用した任意のジオメトリ - ライトビーム — エミッシブ透明マテリアルを適用したCylinderGeometry
ステップ7: マウスパララックス(オプションだが推奨)
マウス移動時にカメラに微妙なオフセットを追加し、奥行き知覚を高めます:
const mouse = { x: 0, y: 0 };
document.addEventListener('mousemove', (e) => {
mouse.x = (e.clientX / window.innerWidth - 0.5) * 2; // -1 から 1
mouse.y = (e.clientY / window.innerHeight - 0.5) * 2;
});
// レンダリングループ内で、カメラにわずかなオフセットを追加
const parallaxStrength = 0.3;
camera.position.x = camAnim.x + mouse.x * parallaxStrength;
camera.position.y = camAnim.y - mouse.y * parallaxStrength * 0.5;
ルームウォークスルーパターン
建築/不動産ウォークスルーの場合、シンプルなジオメトリで部屋を作成します:
// 壁、床、天井にBoxGeometryを使用して部屋を作成
function createRoom(width, height, depth, position, color) {
const mat = new THREE.MeshStandardMaterial({ color, side: THREE.BackSide });
const room = new THREE.Mesh(new THREE.BoxGeometry(width, height, depth), mat);
room.position.copy(position);
scene.add(room);
return room;
}
// シンプルなジオメトリで家具のプレースホルダーを作成
// ソファ = 広くて平らな箱、テーブル = 円柱の上の薄い箱、ランプ = 円柱 + 球
// 部屋内に暖かみのあるエミッシブPointLightを配置
ルームウォークスルーの重要な原則:
- 壁を内側からレンダリングするためにマテリアルで
THREE.BackSideを使用 - 各部屋内に暖色の
PointLight光源を配置(色0xffeedd、強度 0.8) - カメラパスは壁を貫通せず、ドアの開口部から入るようにする
- 入室時に各部屋を自然に見渡せるようにcamera.lookAtをアニメーション
- 昼光をシミュレートするために、エミッシブで明るいマテリアルの窓の長方形を追加
避けるべきアンチパターン
- ❌
OrbitControlsを使用しない — スクロールのみをナビゲーションとする - ❌ 外部のGLTF/GLBモデルを読み込まない — HTMLファイル内で自己完結させる
- ❌
THREE.CapsuleGeometryを使用しない — r128では利用不可 - ❌ キャンバスにグローバルに
pointer-events: noneを設定しない — レンダリングループがキャンバスを必要とする - ❌
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))を忘れない — RetinaでGPU過負荷を防止 - ❌ カメラを
camera.rotationで直接アニメーションしない — 安定した結果を得るために、アニメーション化されたターゲット座標でcamera.lookAt()を使用 - ❌ スクロールコンテナを短くしすぎない — 意味のある移動のために最低400vh、できれば600vh以上
美的方向性
frontend-designスキルと同じ創造的な大胆さを適用してください。各3Dスクロールページはユニークであるべきです:
- カラームードを選択: ネオンサイバーパンク、暖かい夕日、深海、クリスタルの氷、エミッシブアクセントのある暗黒の虚空など
- ジオメトリ言語を選択: 有機的な曲線 vs 硬いエッジ、まばら vs 密集、大きなモノリス vs 小さなパーティクル
- タイポグラフィオーバーレイ: 特徴的なGoogle Fontsをインポート。大きく、シネマティックなタイプを使用。スクロールに応じて透明度とトランスフォームをアニメーション
- 3DシーンとHTMLコンテンツは、一貫した体験として感じられるべきであり、テキストが貼り付けられただけの3D背景であってはならない
クイックリファレンス: CDN URL
Three.js r128: https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js
GSAP 3.12.5: https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js
ScrollTrigger: https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js