В Three.js сцена отрисовывается внутри элемента
<canvas>, который является контейнером для
WebGL-графики. В большинстве случаев взаимодействие с элементами
интерфейса требует наложения HTML-компонентов поверх этого canvas.
HTML-оверлей позволяет размещать текстовые подписи, кнопки,
информационные панели и другие элементы UI, синхронизированные с
3D-сценой.
Структура DOM Элемент
<canvas> располагается внутри контейнера, который
может быть обычным <div>. Все HTML-элементы,
предназначенные для оверлея, помещаются поверх canvas с помощью
абсолютного позиционирования (position: absolute;).
<div id="container" style="position: relative; width: 800px; height: 600px;">
<canvas id="threeCanvas"></canvas>
<div id="overlay" style="position: absolute; top: 0; left: 0; pointer-events: none;"></div>
</div>
Ключевой момент: использование
pointer-events: none на оверлее предотвращает блокировку
взаимодействия с canvas.
Синхронизация позиции Чтобы HTML-элемент
следовал за 3D-объектом, необходимо преобразовать координаты объекта из
3D-пространства в экранные координаты. Three.js предоставляет метод
Vector3.project(camera) для проекции.
const vector = new THREE.Vector3();
const widthHalf = window.innerWidth / 2;
const heightHalf = window.innerHeight / 2;
function updateOverlayPosition(object3D, overlayElement, camera) {
vector.copy(object3D.position);
vector.project(camera);
const x = (vector.x * widthHalf) + widthHalf;
const y = -(vector.y * heightHalf) + heightHalf;
overlayElement.style.transform = `translate(-50%, -50%) translate(${x}px, ${y}px)`;
}
Здесь vector.project(camera) преобразует 3D-координаты в
нормализованные координаты устройства (NDC), а последующее
масштабирование переводит их в координаты экрана.
Обновление при рендеринге Для динамичных сцен позиция оверлеев обновляется в цикле рендера:
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
updateOverlayPosition(mesh, document.getElementById('overlay'), camera);
}
animate();
Это гарантирует точное позиционирование при вращении камеры или движении объекта.
Для нескольких элементов можно хранить массив объектов с их соответствующими HTML-элементами и обновлять их позицию циклически:
const overlays = [
{ object: mesh1, element: document.getElementById('overlay1') },
{ object: mesh2, element: document.getElementById('overlay2') }
];
function updateOverlays() {
overlays.forEach(({ object, element }) => updateOverlayPosition(object, element, camera));
}
Вызывается внутри animate() после рендера сцены.
Скрытие объектов вне экрана: если объект
находится за камерой или за пределами видимой области, оверлей следует
скрыть. Это можно сделать проверкой vector.z после
project():
if (vector.z < -1 || vector.z > 1) {
overlayElement.style.display = 'none';
} else {
overlayElement.style.display = 'block';
}Масштабирование и адаптивность: при изменении
размера окна необходимо пересчитывать widthHalf и
heightHalf, а также обновлять размеры контейнера и
canvas:
window.addEventListener('resize', () => {
widthHalf = window.innerWidth / 2;
heightHalf = window.innerHeight / 2;
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});Стилизация оверлеев: CSS позволяет применять анимации, шрифты, цвета и тени для элементов, не затрагивая WebGL. Это удобно для создания подсказок или HUD-интерфейсов.
HTML-оверлей может обрабатывать клики, наведение и другие события без влияния на WebGL-сцену. Если необходимо реагировать на клики по 3D-объектам, рекомендуется использовать Raycaster для определения попаданий и синхронизировать их с оверлеем.
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
window.addEventListener('click', (event) => {
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, true);
if (intersects.length > 0) {
console.log('Clicked on', intersects[0].object);
}
});
requestAnimationFrame для синхронизации
обновлений.HTML-оверлей в Three.js обеспечивает гибкое и мощное средство интеграции UI с 3D-графикой. Правильное управление проекцией координат, видимостью и обновлением элементов позволяет создавать информативные и интерактивные интерфейсы без ущерба для производительности сцены.