Frontend 3D — Sitios Web 3D Controlados por Scroll
Crea páginas HTML inmersivas en un solo archivo donde el desplazamiento guía al usuario a través de una escena 3D construida con Three.js. El contenido (títulos, texto, imágenes, CTA) se superpone o incrusta dentro del mundo 3D. Cada página DreamWalk es un artefacto .html autocontenido — sin herramientas de compilación, sin npm, sin React.
Stack Tecnológico
Todos los resultados son artefactos HTML de un solo archivo. Sin herramientas de compilación, sin npm, sin React — solo un archivo .html autocontenido.
| Librería | CDN | Propósito |
|---|---|---|
| Three.js r128 | https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js | Motor de renderizado 3D |
| GSAP 3.12.5 | https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js | Motor de animación |
| ScrollTrigger 3.12.5 | https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js | Vinculación scroll-animación |
¿Por qué este stack? Three.js es el framework WebGL dominante con el ecosistema más grande. GSAP ScrollTrigger es el estándar de la industria para mapear la posición del scroll a líneas de tiempo de animación. Juntos impulsan la mayoría de los sitios web 3D galardonados (ver Awwwards, FWA). Esta combinación funciona en un solo archivo HTML sin paso de compilación, perfecto para artefactos.
Importante: Limitaciones de la API de Three.js r128. Esta NO es la última versión de Three.js. Los siguientes elementos NO existen en r128 y nunca deben usarse:
CapsuleGeometry,RoundedBoxGeometry,THREE.MathUtils.seededRandom,WebGPURenderer,THREE.ColorManagement. Siempre usa primitivasBufferGeometry(BoxBufferGeometry,SphereBufferGeometry, etc.) o sus alias (BoxGeometry,SphereGeometry).
Patrón de Arquitectura
┌─────────────────────────────────────────┐
│ Página HTML │
│ ┌───────────────────────────────────┐ │
│ │ <canvas> - Escena Three.js (fijo) │ │
│ │ • Cámara en una ruta/spline │ │
│ │ • Objetos 3D (geometría/partículas) │
│ │ • Iluminación y niebla │ │
│ └───────────────────────────────────┘ │
│ ┌───────────────────────────────────┐ │
│ │ <div class="scroll-container"> │ │
│ │ height: 500vh+ (desplazable) │ │
│ │ Secciones con texto/contenido │ │
│ │ superpuestas mediante │ │
│ │ position:fixed o desvanecidas │ │
│ │ en disparadores de scroll │ │
│ └───────────────────────────────────┘ │
│ │
│ GSAP ScrollTrigger mapea % de scroll → │
│ camera.position / camera.lookAt / │
│ transformaciones de objetos / params │
└─────────────────────────────────────────┘
Cómo Construir una Página 3D con Scroll
Lee references/PATTERNS.md para patrones detallados listos para copiar y pegar antes de escribir código. Contiene más de 40 patrones listos para producción: animación de cámara, iluminación, shaders, partículas, geometría procedural y optimización de rendimiento — todos compatibles con Three.js r128.
Paso 1: Diseño de la Escena
Decide el tipo de experiencia según la intención del usuario:
| Tipo | Comportamiento de la Cámara | Mejor Para |
|---|---|---|
| Túnel / Corredor | Volar hacia adelante a lo largo del eje Z | Revelaciones de producto, narrativa |
| Órbita / Exhibición | Rotar alrededor de un objeto central | Páginas de producto, portafolios |
| Sobrevuelo de Paisaje | Barrer sobre terreno/ciudad | Páginas de aterrizaje, introducciones |
| Recorrido por Habitaciones | Moverse a través de espacios conectados | Visitas virtuales, presentaciones |
| Descenso Vertical | La cámara desciende en el eje Y | Líneas de tiempo, capas de contenido |
| Trayectoria Spline | La cámara sigue una ruta 3D curva | Cinematográfico, editorial |
Paso 2: Andamiaje del HTML
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Experiencia 3D</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; /* re-habilitar para elementos interactivos */ }
</style>
</head>
<body>
<!-- El canvas de Three.js se crea programáticamente -->
<div class="scroll-container">
<!-- Las secciones generan altura de scroll; el contenido se superpone a la escena 3D -->
<div class="section" id="section-1">...</div>
<div class="section" id="section-2">...</div>
<!-- Agrega más secciones = más distancia de scroll = viaje de cámara más largo -->
</div>
<script src="THREE_CDN"></script>
<script src="GSAP_CDN"></script>
<script src="SCROLLTRIGGER_CDN"></script>
<script>
// Configuración de escena, animación, enlaces de ScrollTrigger
</script>
</body>
</html>
Paso 3: Configuración Principal de Three.js
Incluye siempre estos fundamentos:
- Escena + Cámara + Renderizador — Usa
PerspectiveCameracon FOV 60-75 para sensación inmersiva - Iluminación — Como mínimo: un
AmbientLight+ unDirectionalLight. AgregaPointLightoSpotLightpara efecto dramático - Niebla —
scene.fog = new THREE.FogExp2(color, density)añade profundidad y oculta el pop-in - Manejador de redimensionamiento — Siempre maneja
window.resize - Bucle de renderizado —
requestAnimationFrameconrenderer.render(scene, camera)
Paso 4: Animación Scroll → Cámara con GSAP
El patrón de enlace crítico:
gsap.registerPlugin(ScrollTrigger);
// Almacena los objetivos de animación de la cámara como un objeto plano
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 segundo de suavizado
}
});
// Encadena fotogramas clave de la cámara
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 });
// En el bucle de renderizado, aplica los valores animados
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);
}
Paso 5: Superposición de Contenido
Superpone contenido HTML que aparece/desaparece en posiciones de scroll:
// Desvanece una sección cuando la cámara llega a un punto de referencia
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
}
}
);
Paso 6: Pulido Visual
Aplica estos consejos para pasar de básico a impresionante:
- Partículas —
THREE.PointsconTHREE.BufferGeometrypara polvo/estrellas flotantes - Brillo post-procesamiento — Usa materiales emisivos + colores brillantes tipo bloom
- Transiciones de color — Anima
scene.backgroundyscene.fog.colora lo largo del scroll - Revelación de objetos — Los objetos escalan desde 0 o se desvanecen al acercarse la cámara
- Capas de paralaje — Objetos a diferentes distancias se mueven a diferentes velocidades
- Rotación sutil — Rota lentamente objetos decorativos en el bucle de renderizado (independiente del scroll)
- Paralaje de ratón — Ligero desplazamiento de cámara basado en la posición del ratón para sensación de profundidad
Principios de Diseño
- Rendimiento primero — Mantén la geometría simple. Usa
BufferGeometry, limita las llamadas de dibujo, usafogpara ocultar objetos lejanos. Apunta a 60fps - Scroll suave —
scrub: 1oscrub: 2en ScrollTrigger para movimiento sedoso. Nunca usesscrub: true(instantáneo, entrecortado) - Contenido legible — Las superposiciones de texto necesitan contraste. Usa paneles oscuros semitransparentes detrás de texto claro, o asegúrate de que el fondo 3D sea oscuro/borroso detrás de las áreas de texto
- Alternativa móvil — El scroll táctil funciona con ScrollTrigger. Considera reducir el recuento de partículas y la complejidad de geometría en móvil mediante comprobaciones de
window.innerWidth - Carga elegante — Muestra una pantalla de carga CSS simple y ocúltala cuando la escena Three.js esté lista
Objetos 3D Comunes para Construir (sin modelos externos)
Todos pueden crearse con geometría integrada de Three.js — no se requieren archivos GLTF:
- Formas geométricas flotantes — BoxGeometry, IcosahedronGeometry, TorusKnotGeometry con MeshStandardMaterial
- Terreno — PlaneGeometry con desplazamiento de vértices (ondas senoidales, ruido)
- Campos de partículas — BufferGeometry + Points para estrellas, polvo, nieve, visualización de datos
- Suelos de rejilla — GridHelper o geometría de líneas personalizada
- Tubos/túneles — TubeGeometry a lo largo de una ruta CatmullRomCurve3
- Texto — Texturas de Canvas renderizadas en PlaneGeometry, o basadas en sprites
- Objetos wireframe — Cualquier geometría con material
wireframe: truepara un aspecto tecnológico - Haces de luz — CylinderGeometry con material emisivo transparente
Paso 7: Paralaje de Ratón (Opcional pero Recomendado)
Agrega un desplazamiento sutil de la cámara al mover el ratón para percepción de profundidad:
const mouse = { x: 0, y: 0 };
document.addEventListener('mousemove', (e) => {
mouse.x = (e.clientX / window.innerWidth - 0.5) * 2; // -1 a 1
mouse.y = (e.clientY / window.innerHeight - 0.5) * 2;
});
// En el bucle de renderizado, agrega un ligero desplazamiento a la cámara
const parallaxStrength = 0.3;
camera.position.x = camAnim.x + mouse.x * parallaxStrength;
camera.position.y = camAnim.y - mouse.y * parallaxStrength * 0.5;
Patrón de Recorrido por Habitaciones
Para recorridos arquitectónicos/inmobiliarios, construye habitaciones a partir de geometría simple:
// Crea una habitación con BoxGeometry para paredes, suelo, techo
function createRoom(ancho, alto, profundidad, posicion, color) {
const mat = new THREE.MeshStandardMaterial({ color, side: THREE.BackSide });
const room = new THREE.Mesh(new THREE.BoxGeometry(ancho, alto, profundidad), mat);
room.position.copy(posicion);
scene.add(room);
return room;
}
// Crea marcadores de muebles con geometría simple
// Sofá = caja ancha y plana, Mesa = caja delgada sobre cilindros, Lámpara = cilindro + esfera
// Usa PointLights emisivas dentro de las habitaciones para una sensación cálida interior
Principios clave para recorridos por habitaciones:
- Usa
THREE.BackSideen los materiales para que las paredes se rendericen desde el interior - Coloca fuentes
PointLightcálidas dentro de cada habitación (color0xffeedd, intensidad 0.8) - La ruta de la cámara debe entrar a través de aberturas de puertas, no atravesar paredes
- Anima camera.lookAt para escanear naturalmente cada habitación al entrar
- Agrega rectángulos de ventana con material brillante emisivo para simular luz diurna
Anti-Patrones a Evitar
- ❌ No uses
OrbitControls— el scroll debe ser la única navegación - ❌ No cargues modelos GLTF/GLB externos — mantén todo autocontenido en el archivo HTML
- ❌ No uses
THREE.CapsuleGeometry— no está disponible en r128 - ❌ No establezcas
pointer-events: noneen el canvas globalmente — el bucle de renderizado necesita el canvas - ❌ No olvides
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))— evita sobrecarga de GPU en retina - ❌ No animes la cámara directamente con
camera.rotation— usacamera.lookAt()con coordenadas objetivo animadas para resultados estables - ❌ No hagas el contenedor de scroll demasiado corto — mínimo 400vh para un viaje significativo, preferible 600vh+
Dirección Estética
Aplica la misma audacia creativa del skill frontend-design. Cada página 3D con scroll debe sentirse única:
- Elige un estado de ánimo de color: cyberpunk neón, atardecer cálido, océano profundo, hielo cristalino, vacío oscuro con acentos emisivos, etc.
- Elige un lenguaje de geometría: curvas orgánicas vs bordes duros, disperso vs denso, grandes monolitos vs partículas diminutas
- Tipografía superpuesta: importa fuentes de Google distintivas. Usa tipografía grande y cinematográfica. Anima opacidad y transformación al hacer scroll
- La escena 3D y el contenido HTML deben sentirse como una experiencia cohesiva, no un fondo 3D con texto pegado
Referencia Rápida: URLs CDN
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