Реакция на ввод: мышь и клавиатура
Three.js рисует, но не слушает ввод за вас. Клики и клавиши — это обычные браузерные события, которые вы связываете со сценой.
Ввод в Three.js — это стандартные DOM-события браузера. Вы их ловите и меняете объекты сцены; рисование происходит в цикле рендера.
Клавиатура: хранить состояние
Наивный подход — двигать объект прямо в обработчике keydown — даёт рывки: браузер шлёт события с задержкой автоповтора. Правильнее хранить, какие клавиши сейчас зажаты, а применять это в цикле рендера каждый кадр.
const keys = {};
window.addEventListener('keydown', (e) => { keys[e.code] = true; });
window.addEventListener('keyup', (e) => { keys[e.code] = false; });
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const speed = 5;
if (keys['KeyW']) player.position.z -= speed * delta;
if (keys['KeyS']) player.position.z += speed * delta;
if (keys['KeyA']) player.position.x -= speed * delta;
if (keys['KeyD']) player.position.x += speed * delta;
renderer.render(scene, camera);
}
Обратите внимание: движение умножено на delta из прошлого урока — скорость одинакова на любом мониторе.
Мышь: пиксели в NDC
Для 3D-взаимодействий экранные координаты мыши переводят в нормализованные координаты устройства (NDC): центр канваса — (0, 0), края — от -1 до 1. Это нужно, например, для пикинга в следующем уроке.
Посчитаем перевод вживую: где окажется клик в пикселях в системе NDC для канваса 800×600.
function toNDC(px, py, width, height) {
const x = (px / width) * 2 - 1;
const y = -(py / height) * 2 + 1; // ось Y в экране вниз, в NDC — вверх
return { x: +x.toFixed(3), y: +y.toFixed(3) };
}
console.log('Центр (400,300):', toNDC(400, 300, 800, 600));
console.log('Левый верх (0,0):', toNDC(0, 0, 800, 600));
console.log('Правый низ (800,600):', toNDC(800, 600, 800, 600));
Вывод:
Центр (400,300): { x: 0, y: 0 }
Левый верх (0,0): { x: -1, y: 1 }
Правый низ (800,600): { x: 1, y: -1 }
Центр канваса даёт (0,0), углы — крайние ±1. Заметьте, что ось Y инвертируется: в экране она растёт вниз, а в NDC — вверх.
Итог
- Ввод — это DOM-события; Three.js их не перехватывает сам.
- Состояние клавиш храните в объекте, применяйте в цикле с delta.
- Координаты мыши переводят в NDC (-1..1), ось Y инвертируется.