12k
All articles

Primeros pasos con ThreeUI

Configura ThreeUI en React, añade un fondo 3D animado, corrige las rutas de recursos y optimiza el rendimiento con carga diferida y alternativas para movimiento reducido.

OpenReplay Team
OpenReplay Team
Primeros pasos con ThreeUI

ThreeUI es un catálogo de componentes de React creado por Meng To, publicado en threeui.com y en npm como @designcodeio/threeui. Cada componente incluye su propio renderizador animado (Three.js, WebGL nativo o Canvas 2D, según el componente), de modo que para añadir un fondo 3D animado a una sección hero basta con importar un componente, en lugar de construir una escena, una cámara y unos materiales.

Quieres una sección hero que detenga el scroll, pero cualquier tutorial de Three.js empieza con grafos de escena, esquemas de iluminación y bucles de renderizado antes de que aparezca algo en pantalla. Esta guía explica cómo instalar ThreeUI, renderizar un componente de fondo detrás de una sección hero, resolver el problema de las rutas de los recursos y decidir si el peso adicional compensa en tu página.

Puntos clave

  • Instala ThreeUI con npm install @designcodeio/threeui e importa @designcodeio/threeui/style.css una sola vez desde el punto de entrada de tu aplicación.
  • ThreeUI declara react y react-dom (18 o 19) y three como dependencias peer.
  • Los componentes que renderizan un documento HTML completo cargan archivos de runtime desde URL relativas a la raíz, así que debes copiarlos desde node_modules/@designcodeio/threeui/lib-dist/assets/ o configurar sourceUrl o assetBaseUrl.
  • Cualquier cambio que vaya más allá de las variantes y los controles expuestos por un componente implica editar su código fuente.
  • Carga los componentes de ThreeUI de forma diferida (lazy loading), omítelos cuando prefers-reduced-motion esté activado y usa una imagen estática cuando el efecto 3D no aporte nada.

¿Qué es ThreeUI y para quién está pensado?

ThreeUI ofrece secciones animadas listas para usar (heroes, fondos, elementos interactivos) que se integran en una página React convencional. No necesitas saber cómo funciona un grafo de escena: eliges un componente, lo renderizas y configuras sus props.

Existen varios proyectos independientes llamados three-ui, entre ellos poki-archive/three-ui y nirholas/three-ui. Esta guía trata sobre el ThreeUI de Meng To, disponible en threeui.com y en el repositorio MengTo/threeui.

ThreeUI tiene dos niveles: Community y Pro. Los componentes Community tienen licencia MIT y se instalan desde npm. Los componentes Pro no están en npm: se descargan como código fuente en tu proyecto con npx @designcodeio/threeui-cli tras iniciar sesión con un plan de pago activo. El proyecto es reciente (Community se liberó como código abierto en agosto de 2026), así que es de esperar que la API cambie.

Instalar el paquete de ThreeUI

Instala un único paquete de npm y luego importa su hoja de estilos una sola vez. La página de instalación de ThreeUI explica la configuración paso a paso. El paquete publicado declara como dependencias peer react y react-dom desde la versión 18 hasta la 20 (sin incluirla), además de three a partir de la 0.149. npm 7 y versiones posteriores instalan automáticamente las dependencias peer que falten. La CLI Pro requiere Node.js 20 o superior.

npm install @designcodeio/threeui

El lugar donde se importa la hoja de estilos depende del framework:

FrameworkDónde va la importación del CSS
Vitesrc/main.jsx
Next.js App Routerapp/layout.jsx
// src/main.jsx (Vite)
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "@designcodeio/threeui/style.css";
import App from "./App";

createRoot(document.getElementById("root")).render(
  <StrictMode>
    <App />
  </StrictMode>
);

Añadir un componente

Para renderizar un componente de ThreeUI, impórtalo por su nombre y colócalo en tu JSX. El ejemplo del README usa AtTheHorizon, pero ese componente no se exporta en la versión actual del paquete (1.2.0), así que esta guía utiliza EmeraldHorizonBackground, un fondo animado con Three.js que se sitúa detrás de una sección hero:

import { EmeraldHorizonBackground } from "@designcodeio/threeui";

export function Hero() {
  return <EmeraldHorizonBackground />;
}

La importación desde la raíz es la opción más sencilla. El paquete también ofrece una subruta por componente, que carga menos código durante el desarrollo:

import { EmeraldHorizonBackground } from "@designcodeio/threeui/components/EmeraldHorizonBackground";

Las props varían de un componente a otro. Consúltalas en la página de cada componente en threeui.com. Por ejemplo, Brand Orbs acepta variant, size, mode, speed y paused. No intentes adivinar las props. Para añadir una interacción sin depender de ninguna prop, usa el estado del componente contenedor:

import { useState } from "react";
import { EmeraldHorizonBackground } from "@designcodeio/threeui";

export function Hero() {
  const [show3D, setShow3D] = useState(true);

  return (
    <section>
      {show3D ? (
        <EmeraldHorizonBackground />
      ) : (
        <img src="/hero-fallback.jpg" alt="Product hero" />
      )}
      <button onClick={() => setShow3D((v) => !v)}>
        {show3D ? "Show static image" : "Show 3D"}
      </button>
    </section>
  );
}

El problema de los recursos en ThreeUI

Algunos componentes de ThreeUI renderizan un documento HTML completo. Obtienen sus archivos de runtime desde rutas fijas en la raíz de tu sitio, las mismas que usa el sitio de vista previa de ThreeUI. Landscape, por ejemplo, solicita /landscape.html de forma predeterminada. Si tu aplicación no sirve un archivo en esa ruta, el componente falla. Hay dos formas de solucionarlo: copiar los archivos que necesites desde node_modules/@designcodeio/threeui/lib-dist/assets/ a tu carpeta pública o, si el componente dispone de una prop sourceUrl o assetBaseUrl, apuntarla a la ubicación donde alojes los archivos.

# Check the network tab for the exact paths the component requests,
# then mirror that layout under public/.
cp -R node_modules/@designcodeio/threeui/lib-dist/assets/. public/
// Only if the component's page lists this prop:
// <SomeComponent assetBaseUrl="/threeui/" />
SíntomaSolución
El área del componente aparece vacía; la pestaña de red muestra errores 404 en la ruta raízCopia los recursos necesarios a public/ respetando las mismas rutas
Los recursos están en una CDN o en una subrutaConfigura sourceUrl o assetBaseUrl cuando el componente lo permita

Cómo encaja ThreeUI con Three.js puro

ThreeUI oculta el renderizador. En los componentes basados en Three.js, la escena, la cámara, el renderizador, los materiales y el bucle de animación residen dentro del componente. Otros componentes usan WebGL nativo o Canvas 2D. El precio de esa comodidad es el control: ThreeUI expone las variantes y los controles de cada componente, y modificar cualquier aspecto que estos no cubran implica editar el código fuente del componente. Puedes leer el código fuente de Community en node_modules y en GitHub. La CLI Pro copia el código fuente Pro en tu proyecto.

Si prevés ir más allá de los controles expuestos, aprende la biblioteca subyacente. Building 3D animations using JavaScript and Three.js cubre los fundamentos.

Rendimiento de ThreeUI, sin rodeos

Cada componente de ThreeUI ejecuta un canvas animado en tiempo real, lo que tiene un coste en JavaScript, descarga de recursos y tiempo de GPU. Las GPU de los móviles son las que más lo notan. Carga los componentes de forma diferida, omítelos para los visitantes que tengan activado prefers-reduced-motion y usa una imagen estática allí donde el efecto 3D no aporte nada a la página.

React.lazy espera una exportación por defecto, así que debes mapear la exportación con nombre:

import { lazy, Suspense, useEffect, useState } from "react";

const EmeraldHorizonBackground = lazy(() =>
  import("@designcodeio/threeui").then((m) => ({ default: m.EmeraldHorizonBackground }))
);

function useReducedMotion() {
  const [reduced, setReduced] = useState(false);
  useEffect(() => {
    const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
    setReduced(mq.matches);
    const onChange = (e) => setReduced(e.matches);
    mq.addEventListener("change", onChange);
    return () => mq.removeEventListener("change", onChange);
  }, []);
  return reduced;
}

function hasWebGL() {
  const canvas = document.createElement("canvas");
  return Boolean(canvas.getContext("webgl2") || canvas.getContext("webgl"));
}

const fallback = <img src="/hero-fallback.jpg" alt="Product hero" />;

export function Hero() {
  const reduced = useReducedMotion();
  const [webgl, setWebgl] = useState(false);
  useEffect(() => setWebgl(hasWebGL()), []);

  if (reduced || !webgl) return fallback;
  return <Suspense fallback={fallback}><EmeraldHorizonBackground /></Suspense>;
}

El componente Hero anterior lee la media feature prefers-reduced-motion mediante window.matchMedia y comprueba si hay un contexto disponible con HTMLCanvasElement.getContext. Algunos componentes gestionan por sí mismos la reducción de movimiento. Brand Orbs, por ejemplo, tiene las props speed y paused, y su código fuente comprueba prefers-reduced-motion y se pausa cuando no está visible. Consulta la página de cada componente para saber qué cubre.

En Next.js, usa next/dynamic. La opción ssr: false solo funciona dentro de un Client Component, y Next.js lanza un error si la usas en un Server Component. Desactivar el renderizado en el servidor es una opción segura por defecto para el código de canvas que solo se ejecuta en el navegador:

"use client";
import dynamic from "next/dynamic";

const EmeraldHorizonBackground = dynamic(
  () => import("@designcodeio/threeui").then((m) => m.EmeraldHorizonBackground),
  { ssr: false, loading: () => <img src="/hero-fallback.jpg" alt="Product hero" /> }
);

export default function Hero() {
  return <EmeraldHorizonBackground />;
}

Consulta la guía de lazy loading de Next.js para más detalles. Ejecuta el analizador de bundles de tu herramienta de build para ver cuánto añade realmente ThreeUI a tu bundle. Aun así, las pruebas de laboratorio solo muestran una parte del panorama. Una herramienta de session replay como OpenReplay te permite ver visitas reales, de modo que puedas detectar una sección hero que se queda en blanco o se entrecorta en móviles más lentos. Si necesitas más control del que ofrece un componente prediseñado, las opciones de más bajo nivel se tratan en WebGPU vs WebGL: Why the Industry Is Moving On.

Fija la versión del paquete de ThreeUI. Según las reglas de publicación del README, una versión de Community se publica cuando un maintainer fusiona el pull request de sincronización revisado, y eliminar un componente, variante o control público implica una versión major. AtTheHorizon es un ejemplo: se incluyó en la 0.3.0 y ya no está en las versiones 1.x. Revisa las notas de la versión antes de actualizar.

Conclusión

ThreeUI te proporciona un fondo 3D funcional para tu sección hero con una instalación de npm, una importación de hoja de estilos y un componente. Reserva tiempo para servir los recursos de runtime y ten en cuenta que sacrifica control a cambio de rapidez. Empieza renderizando un componente Community dentro de un límite de carga diferida con una alternativa para movimiento reducido. Después, mide el bundle y haz pruebas en un móvil de gama media antes de decidir si se queda en la página.

Preguntas frecuentes

¿Puedo usar los componentes Community de ThreeUI en un proyecto comercial?

Sí. El código de la aplicación, el código de los componentes y las imágenes creadas por ThreeUI en la edición Community tienen licencia MIT, que permite el uso comercial siempre que conserves el aviso de licencia. Las fuentes abiertas incluidas siguen bajo la SIL Open Font License 1.1, y los archivos de runtime de Three.js incluidos siguen bajo licencia MIT. Los componentes Pro son un producto de pago independiente, así que revisa las condiciones de Pro antes de publicarlos.

¿Qué ocurre si vuelvo a ejecutar la CLI Pro de ThreeUI después de editar un componente descargado?

La CLI Pro de ThreeUI no sustituye los archivos que hayas editado a menos que añadas el flag --force, por ejemplo npx @designcodeio/threeui-cli add cross-beam --dir ./src --force. Usar --force reemplaza tus cambios con el código fuente descargado, así que haz commit de tus cambios primero y vuelve a integrarlos manualmente. Ejecuta npx @designcodeio/threeui-cli --help para ver el resto de comandos y flags, incluidos login y logout.

¿Por qué los componentes Pro de ThreeUI no aparecen en package.json ni en npm update?

Los componentes Pro no son una dependencia de npm. La CLI de ThreeUI copia su código fuente directamente en tu proyecto, por lo que no figuran en package.json, y ni npm update, ni npm outdated, ni los escáneres de dependencias basados en el lockfile los rastrean. Trata los archivos Pro como código vendorizado: mantenlos bajo control de versiones y vuelve a descargarlos con la CLI cuando quieras una versión más reciente.

¿Todos los componentes de ThreeUI necesitan WebGL?

No. Algunos componentes de ThreeUI dibujan con Canvas 2D en lugar de WebGL. El preset DesignCode de Brand Orbs, por ejemplo, dibuja su campo de puntos con Canvas 2D. Una comprobación genérica de WebGL oculta estos componentes en navegadores que sí podrían ejecutarlos, así que aplica una comprobación con getContext('webgl2') o getContext('webgl') solo a los componentes cuya página en threeui.com indique un renderizador de Three.js o WebGL.

DevTools for the frontend

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.