Three.js — это библиотека JavaScript для создания 3D-графики в браузере на основе WebGL. Она позволяет добавлять интерактивные элементы на сайт без необходимости писать код с нуля на уровне OpenGL. Главное отличие от стандартных библиотек: Three.js предоставляет готовый слой абстракции над сложными API графики, упрощая работу со сценами, камерой и материалами. Это не просто визуальный эффект, а инструмент для создания полноценных интерактивных интерфейсов, где пользователь может вращать модели, менять параметры или взаимодействовать с объектами напрямую.

Введение: роль Three.js в веб-разработке и отличие от стандартных библиотек

Three.js — это библиотека JavaScript для создания 3D-графики в браузере на основе WebGL. Она позволяет добавлять интерактивные элементы на сайт без необходимости писать код с нуля на уровне OpenGL.

Главное отличие от стандартных библиотек: Three.js предоставляет готовый слой абстракции над сложными API графики, упрощая работу со сценами, камерой и материалами. Это не просто визуальный эффект, а инструмент для создания полноценных интерактивных интерфейсов, где пользователь может вращать модели, менять параметры или взаимодействовать с объектами напрямую.

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

Шаг 1. Подготовка окружения: установка зависимостей и базовая конфигурация проекта

Для работы с Three.js не обязательно устанавливать Node.js, но использование пакетного менеджера упрощает управление версиями. Можно подключить библиотеку через CDN или npm.

Пример подключения через CDN в HTML-файле:

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>

Использование модулей ES6 (рекомендуемый способ):

import * as THREE from 'three';

import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

Важно: современные версии Three.js используют модульную систему. Старые пути импорта могут не работать в новых сборках.

Создайте файл index.html и подключите скрипт. Убедитесь, что сервер локального развития запущен (например, через VS Code Live Server), так как браузеры блокируют загрузку модулей с диска из соображений безопасности.

Шаг 2. Создание сцены, камеры и рендерера: фундамент интерактивности

Три основных компонента любой сцены в Three.js — сцена, камера и рендерер.

Сцена (Scene) — это контейнер для всех объектов. Она хранит информацию о свете, атмосфере и других глобальных настройках.

Камера (Camera) определяет точку зрения пользователя. Стандартная PerspectiveCamera имитирует человеческое зрение с перспективой. OrthographicCamera используется для чертежей или изометрии без искажений перспективы.

Рендерер (Renderer) отвечает за отрисовку графики на элементе DOM. WebGLRenderer — стандартный выбор.

Пример кода инициализации:

const scene = new THREE.Scene();

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

const renderer = new THREE.WebGLRenderer({ antialias: true });

renderer.setSize(window.innerWidth, window.innerHeight);

document.body.appendChild(renderer.domElement);

Камера должна быть помещена в сцену (scene.add(camera)), а рендерер — на страницу. Не забудьте добавить обработчик изменения размера окна, чтобы сцена не растягивалась при ресайзе браузера.

Шаг 3. Работа со светом и материалами: реализация физики и текстур

Свет делает сцену реалистичной. В Three.js есть несколько типов источников света.

AmbientLight — общий фоновый свет, заполняющий тени.

DirectionalLight — имитирует солнце, падает под углом и создает жесткие тени.

PointLight — точечный источник, светящийся во все стороны (например, лампочка).

SpotLight — прожектор с конусом света.

Материалы определяют, как объект реагирует на свет. MeshBasicMaterial не учитывает свет (всегда яркий), MeshLambertMaterial реагирует на свет мягко, MeshPhongMaterial создает блики.

Для реалистичности используйте текстуры: загрузите изображение через TextureLoader и примените его к материалу свойства map.

Пример:

const textureLoader = new THREE.TextureLoader();

const material = new THREE.MeshStandardMaterial({ map: texture });

Важно: текстуры должны быть оптимизированы. Слишком большие файлы замедлят загрузку страницы.

Шаг 4. Добавление геометрии и оптимизация мешей для производительности

Геометрия (Geometry) определяет форму объекта. Простые формы: BoxGeometry, SphereGeometry, PlaneGeometry.

Для сложных моделей используйте GLTFLoader или OBJLoader. Формат .glb предпочтителен из-за меньшего размера и поддержки анимаций.

Оптимизация критична для производительности:

1. Уменьшите количество полигонов (треугольников) в моделях, если это не влияет на вид.

2. Используйте InstancedMesh для отрисовки множества одинаковых объектов (например, деревьев или коробок) за один вызов рендеринга.

3. Применяйте LOD (Level of Detail): загружайте более детальные модели только при близком расстоянии пользователя.

Пример создания куба:

const geometry = new THREE.BoxGeometry(1, 1, 1);

const mesh = new THREE.Mesh(geometry, material);

scene.add(mesh);

Не забывайте добавлять объекты в сцену через scene.add(object).

Шаг 5. Реализация пользовательского ввода: обработка мыши, клавиатуры и тач-событий

Интерактивность требует обработки событий. Three.js предоставляет Raycaster — инструмент для определения пересечения луча с объектами.

Raycaster позволяет узнать, на какой объект кликнул пользователь или коснулся пальцем.

Пример кода:

const raycaster = new THREE.Raycaster();

const mouse = new THREE.Vector2();

function onMouseClick(event) {

// Нормализация координат мыши от -1 до 1

mouse.x = (event.clientX / window.innerWidth) * 2 — 1;

mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

raycaster.setFromCamera(mouse, camera);

const intersects = raycaster.intersectObjects(scene.children);

if (intersects.length > 0) {

// Обработка клика по объекту

console.log('Клик по:', intersects[0].object.name);

}

}

document.addEventListener('click', onMouseClick);

Для мобильных устройств используйте touchstart и touchend вместо click, если нужно различать жесты.

Шаг 6. Создание анимации циклов и интерактивных состояний объектов

Анимация в Three.js происходит в цикле рендеринга, который вызывается через requestAnimationFrame.

Функция animate обновляет позицию объектов и вызывает renderer.render.

Пример:

function animate() {

requestAnimationFrame(animate);

mesh.rotation.x += 0.01;

renderer.render(scene, camera);

}

animate();

Интерактивные состояния: меняйте свойства объекта (цвет, прозрачность, позицию) в зависимости от действий пользователя.

Пример изменения цвета при клике:

if (intersects.length > 0) {

intersects[0].object.material.color.set(0xff0000);

}

Избегайте тяжелых вычислений внутри цикла анимации. Переносите логику в отдельные функции или используйте Web Workers для сложных расчетов.

Шаг 7. Интеграция с DOM и адаптация под мобильные устройства

Three.js работает внутри элемента <canvas>, который можно встроить в любой контейнер HTML.

Для интеграции с DOM используйте CSS для позиционирования canvas, но не пытайтесь управлять 3D-объектами через CSS. Используйте JavaScript для изменения стилей элементов интерфейса (кнопок, модальных окон) на основе данных из 3D-сцены.

Адаптация под мобильные устройства:

1. Отключите курсор мыши и используйте touch-события.

2. Уменьшите разрешение рендеринга для мобильных устройств (renderer.setPixelRatio(window.devicePixelRatio < 2 ? 1 : window.devicePixelRatio)).

3. Используйте OrbitControls для управления камерой пальцами.

4. Проверьте производительность на слабых устройствах: отключите тени, сложные материалы или пост-процессинг.

Шаг 8. Оптимизация рендеринга: frustum culling, LOD и управление памятью

Frustum Culling — автоматическое отключение объектов, находящихся за пределами видимости камеры. Three.js делает это по умолчанию.

LOD (Level of Detail) — замена детальных моделей на упрощенные при удалении пользователя.

Управление памятью:

1. Удаляйте неиспользуемые объекты из сцены (scene.remove(object)).

2. Очищайте текстуры и геометрию, если они больше не нужны.

3. Используйте dispose() для освобождения памяти в браузере.

Пример:

object.geometry.dispose();

object.material.dispose();

4. Избегайте создания новых объектов внутри цикла анимации. Создавайте их один раз и переиспользуйте.

Вопросы и ответы

Можно ли использовать Three.js на статических сайтах без сервера?

Да, если библиотека подключена через CDN. Однако для модульного импорта (import) нужен локальный сервер или сборщик типа Webpack/Vite.

Как проверить производительность 3D-сцены?

Используйте инструменты разработчика браузера (Performance tab), следите за FPS. Если падает — упростите геометрию или отключите тени.

// Пример создания сцены и куба
import * as THREE from 'three';

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// Добавление света
const ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);

// Создание куба
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshStandardMaterial({ color: 0xff0000 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

// Анимация
function animate() {
  requestAnimationFrame(animate);
  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;
  renderer.render(scene, camera);
}
animate();