12k
All articles

Начало работы с ThreeUI

Настройте ThreeUI в React, добавьте анимированный 3D-фон для главного экрана, исправьте пути ресурсов и оптимизируйте загрузку с учетом настроек движения.

OpenReplay Team
OpenReplay Team
Начало работы с ThreeUI

ThreeUI — каталог React-компонентов от Менга То (Meng To), опубликованный на threeui.com и в npm под именем @designcodeio/threeui. Каждый компонент поставляется с собственным анимированным рендерером (Three.js, «чистый» WebGL или Canvas 2D, в зависимости от компонента). Поэтому, чтобы добавить анимированный 3D-фон в hero-секцию, достаточно импортировать компонент, а не собирать сцену, камеру и материалы вручную.

Вам нужна hero-секция, от которой невозможно оторвать взгляд, но любой туториал по Three.js начинается с графов сцены, схем освещения и циклов рендеринга, и только потом на экране хоть что-то появляется. В этом руководстве мы разберём установку ThreeUI, рендеринг одного фонового компонента под hero-секцией, решение проблемы с путями к ассетам, а также поможем понять, оправдан ли дополнительный вес на вашей странице.

Ключевые выводы

  • Установите ThreeUI командой npm install @designcodeio/threeui и один раз импортируйте @designcodeio/threeui/style.css в точке входа приложения.
  • В качестве peer-зависимостей ThreeUI указывает react и react-dom (версии 18 или 19), а также three.
  • Компоненты, которые рендерят полноценный HTML-документ, загружают runtime-файлы по URL-адресам относительно корня сайта. Скопируйте эти файлы из node_modules/@designcodeio/threeui/lib-dist/assets/ или задайте sourceUrl либо assetBaseUrl.
  • Всё, что выходит за рамки доступных у компонента вариантов и настроек, требует правки его исходного кода.
  • Загружайте компоненты ThreeUI лениво, не показывайте их при включённом prefers-reduced-motion и используйте статичное изображение там, где 3D-эффект ничего не добавляет.

Что такое ThreeUI и для кого он предназначен?

ThreeUI предоставляет готовые анимированные секции (hero-блоки, фоны, интерактивные элементы), которые можно просто вставить в обычную React-страницу. Знать, как устроен граф сцены, не нужно: вы выбираете компонент, рендерите его и задаёте пропсы.

Существует несколько не связанных между собой проектов с названием three-ui, в том числе poki-archive/three-ui и nirholas/three-ui. Это руководство посвящено ThreeUI от Менга То с сайта threeui.com и из репозитория MengTo/threeui.

ThreeUI доступен в двух вариантах: Community и Pro. Компоненты Community распространяются под лицензией MIT и устанавливаются из npm. Компонентов Pro в npm нет: вы скачиваете их исходный код в свой проект с помощью npx @designcodeio/threeui-cli после входа в аккаунт с активной платной подпиской. Проект молодой (исходный код Community был открыт в августе 2026 года), поэтому будьте готовы к изменениям API.

Установка пакета ThreeUI

Установите один npm-пакет и один раз импортируйте его таблицу стилей. Процесс настройки описан на странице установки ThreeUI. В опубликованном пакете в качестве peer-зависимостей указаны react и react-dom начиная с версии 18 и до 20 (не включительно), а также three начиная с 0.149. npm 7 и более поздние версии устанавливают недостающие peer-зависимости автоматически. Для Pro CLI требуется Node.js 20 или новее.

npm install @designcodeio/threeui

Место импорта таблицы стилей зависит от фреймворка:

ФреймворкКуда добавить импорт 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>
);

Добавляем один компонент

Чтобы отрендерить компонент ThreeUI, импортируйте его по имени и поместите в JSX. В примере из README используется AtTheHorizon, но текущая версия пакета 1.2.0 этот компонент не экспортирует, поэтому в руководстве мы используем EmeraldHorizonBackground — анимированный фон на Three.js, который располагается под hero-секцией:

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

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

Импорт из корня пакета — самый простой вариант. Пакет также предоставляет отдельный subpath для каждого компонента, что позволяет подтягивать меньше кода в процессе разработки:

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

Пропсы у разных компонентов различаются — смотрите их на странице каждого компонента на threeui.com. Например, Brand Orbs принимает variant, size, mode, speed и paused. Не угадывайте пропсы. Чтобы добавить интерактивность, не завися ни от каких пропсов, используйте состояние в родительском компоненте:

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>
  );
}

Подводный камень ThreeUI: ассеты

Некоторые компоненты ThreeUI рендерят полноценный HTML-документ. Они запрашивают свои runtime-файлы по фиксированным путям от корня вашего сайта — тем же, что использует демо-сайт ThreeUI. Например, Landscape по умолчанию запрашивает /landscape.html. Если ваше приложение не отдаёт файл по этому пути, компонент не работает. Исправить это можно двумя способами. Скопируйте нужные файлы из node_modules/@designcodeio/threeui/lib-dist/assets/ в папку public. Либо, если у компонента есть проп sourceUrl или assetBaseUrl, укажите в нём место, где вы размещаете файлы.

# 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/" />
СимптомРешение
Область компонента пустая; во вкладке Network видны ошибки 404 для путей от корняСкопируйте нужные ассеты в public/ по соответствующим путям
Ассеты размещены на CDN или по вложенному путиЗадайте sourceUrl или assetBaseUrl, если компонент их поддерживает

ThreeUI и «чистый» Three.js

ThreeUI скрывает рендерер. В компонентах на базе Three.js сцена, камера, рендерер, материалы и цикл анимации находятся внутри компонента. Другие компоненты используют «чистый» WebGL или Canvas 2D. Платой за удобство становится контроль: ThreeUI открывает только варианты и настройки каждого компонента, а для изменения всего, что ими не покрыто, придётся править исходный код компонента. Исходники Community можно посмотреть в node_modules и на GitHub. Pro CLI копирует исходный код Pro-компонентов прямо в ваш проект.

Если вы планируете выходить за рамки доступных настроек, изучите базовую библиотеку. Основы описаны в статье Building 3D animations using JavaScript and Three.js.

Производительность ThreeUI: без прикрас

Каждый компонент ThreeUI использует живой анимированный canvas, а это JavaScript, загрузка ассетов и нагрузка на GPU. Сильнее всего это ощущают мобильные GPU. Загружайте компоненты лениво, не показывайте их посетителям с включённым prefers-reduced-motion и используйте статичное изображение везде, где 3D-эффект ничего не добавляет странице.

React.lazy ожидает экспорт по умолчанию, поэтому преобразуйте именованный экспорт:

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>;
}

Компонент Hero выше считывает медиафункцию prefers-reduced-motion через window.matchMedia и проверяет доступность контекста с помощью HTMLCanvasElement.getContext. Некоторые компоненты сами учитывают настройку уменьшения анимации. Например, у Brand Orbs есть пропсы speed и paused, а его исходный код проверяет prefers-reduced-motion и ставит анимацию на паузу, когда компонент выходит из области видимости. Что именно поддерживает каждый компонент, смотрите на его странице.

В Next.js используйте next/dynamic. Опция ssr: false работает только внутри Client Component, а при использовании в Server Component Next.js выбрасывает ошибку. Отключение серверного рендеринга — безопасный вариант по умолчанию для canvas-кода, который выполняется только в браузере:

"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 />;
}

Подробности — в руководстве Next.js по ленивой загрузке. Запустите анализатор бандла вашего сборщика, чтобы увидеть, сколько на самом деле ThreeUI добавляет к бандлу. Однако лабораторные тесты показывают лишь часть картины. Инструмент воспроизведения сессий, например OpenReplay, позволяет просматривать реальные визиты и замечать, что hero-секция остаётся пустой или подтормаживает на медленных телефонах. Если вам нужно больше контроля, чем даёт готовый компонент, низкоуровневые варианты рассмотрены в статье WebGPU vs WebGL: Why the Industry Is Moving On.

Зафиксируйте версию пакета ThreeUI. Согласно правилам выпуска релизов из README, релиз Community выходит, когда мейнтейнер мержит прошедший ревью pull request синхронизации, а удаление публичного компонента, варианта или настройки влечёт за собой мажорную версию. Пример — AtTheHorizon: он появился в версии 0.3.0 и отсутствует в релизах 1.x. Перед обновлением изучайте release notes.

Заключение

ThreeUI позволяет получить рабочий 3D-фон для hero-секции с помощью одной установки из npm, одного импорта таблицы стилей и одного компонента. Заложите время на размещение runtime-ассетов и помните, что ThreeUI жертвует контролем ради скорости. Начните с рендеринга одного компонента Community за границей ленивой загрузки и с fallback для режима уменьшения анимации. Затем измерьте бандл и протестируйте страницу на телефоне среднего класса, прежде чем решить, оставлять ли компонент.

Часто задаваемые вопросы

Можно ли использовать компоненты ThreeUI Community в коммерческом проекте?

Да. Код приложения ThreeUI Community, код компонентов и изображения, созданные авторами ThreeUI, распространяются под лицензией MIT, которая разрешает коммерческое использование при условии сохранения уведомления о лицензии. Входящие в комплект открытые шрифты остаются под лицензией SIL Open Font License 1.1, а входящие в комплект runtime-файлы Three.js — под лицензией MIT. Pro-компоненты — отдельный платный продукт, поэтому перед их использованием в продакшене ознакомьтесь с условиями Pro.

Что произойдёт, если повторно запустить ThreeUI Pro CLI после редактирования скачанного компонента?

ThreeUI Pro CLI не перезапишет отредактированные вами файлы, если не добавить флаг --force, например: npx @designcodeio/threeui-cli add cross-beam --dir ./src --force. При использовании --force ваши правки заменяются скачанным исходным кодом, поэтому сначала закоммитьте изменения, а затем вручную перенесите их обратно. Выполните npx @designcodeio/threeui-cli --help, чтобы увидеть остальные команды и флаги, включая login и logout.

Почему компоненты ThreeUI Pro не отображаются в package.json и не обновляются через npm update?

Pro-компоненты не являются npm-зависимостью. ThreeUI CLI копирует их исходный код прямо в ваш проект, поэтому они не указаны в package.json, и их не отслеживают ни npm update, ни npm outdated, ни сканеры зависимостей на основе lock-файлов. Относитесь к Pro-файлам как к vendored-коду: храните их в системе контроля версий и скачивайте заново через CLI, когда нужна более новая версия.

Нужен ли WebGL каждому компоненту ThreeUI?

Нет. Некоторые компоненты ThreeUI отрисовываются с помощью Canvas 2D, а не WebGL. Например, пресет DesignCode компонента Brand Orbs рисует поле точек через Canvas 2D. Сплошная проверка WebGL скроет такие компоненты в браузерах, которые могли бы их запустить, поэтому применяйте проверку getContext('webgl2') или getContext('webgl') только к тем компонентам, на странице которых на threeui.com указан рендерер на Three.js или 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.