В A-Frame взаимодействие с VR-контроллерами осуществляется через
компоненты tracked-controls и их производные, а также через
события, которые генерируются при нажатии кнопок или движении стиков.
Контроллеры передают данные о кнопках,
триггерах, тачпадах и
аналоговых осях, что позволяет реализовать сложное
взаимодействие с виртуальной средой.
Каждый контроллер A-Frame поддерживает стандартные события:
buttondown – срабатывает при нажатии
кнопки. Возвращает объект события с информацией о том, какая кнопка была
нажата.buttonup – срабатывает при отпускании
кнопки.axismove – фиксирует движение стика
или трекпада. Значение осей передается в виде массива
[x, y] с диапазоном от -1 до
1.thumbstickmoved – специализированное
событие для стиков Oculus и других контроллеров.События могут быть привязаны как к отдельным сущностям, так и к сцене
через компонент a-entity.
Пример привязки события к кнопке:
<a-entity id="rightHand"
oculus-touch-controls="hand: right"></a-entity>
const rightHand = document.querySelector('#rightHand');
rightHand.addEventListener('buttondown', (evt) => {
console.log('Нажата кнопка:', evt.detail.id);
});
rightHand.addEventListener('axismove', (evt) => {
const [x, y] = evt.detail.axis;
console.log('Ось стика:', x, y);
});
В объекте события evt.detail содержится информация
о:
id – идентификатор кнопки (trigger,
grip, thumbstick, touchpad и
т.д.);state – текущее состояние кнопки (pressed,
touched, value);axis – массив с координатами осей
[x, y].Кнопки в A-Frame делятся на:
pressed: true/false).value варьируется от 0 до 1.Оси используются для стиков и тачпадов и возвращают координаты
движения. Для стика центр всегда [0, 0], при смещении
значения изменяются в пределах -1 до 1.
Пример обработки триггера с плавной величиной:
rightHand.addEventListener('buttondown', (evt) => {
if (evt.detail.id === 'trigger') {
console.log('Значение триггера:', evt.detail.value);
}
});
A-Frame позволяет использовать платформенно-зависимые контроллеры, например:
oculus-touch-controlsvive-controlswindows-motion-controlsКаждый из этих компонентов автоматически генерирует стандартные
события (buttondown, buttonup,
axismove), но некоторые кнопки могут иметь разные
идентификаторы в зависимости от устройства.
<a-entity id="leftHand" vive-controls="hand: left"></a-entity>
<a-entity id="rightHand" oculus-touch-controls="hand: right"></a-entity>
document.querySelector('#leftHand').addEventListener('buttondown', (evt) => {
if (evt.detail.id === 'grip') {
console.log('Зажат грип левой руки');
}
});
Событие axismove идеально подходит для реализации
перемещения персонажа или поворота камеры. В массиве
[x, y]:
x > 0 – движение вправоx < 0 – движение влевоy > 0 – движение впередy < 0 – движение назадПример движения персонажа по сцене:
const cameraRig = document.querySelector('#cameraRig');
rightHand.addEventListener('axismove', (evt) => {
const [x, y] = evt.detail.axis;
cameraRig.object3D.position.x += x * 0.1;
cameraRig.object3D.position.z += y * 0.1;
});
Здесь значение оси умножается на коэффициент скорости, чтобы движение было плавным и управляемым.
Часто используется комбинация цифровых кнопок и аналоговых осей для реализации сложных действий, например:
Пример комплексной обработки:
rightHand.addEventListener('buttondown', (evt) => {
if (evt.detail.id === 'trigger') {
grabObject();
}
});
rightHand.addEventListener('axismove', (evt) => {
const [x, y] = evt.detail.axis;
moveObject(x, y);
});
Такой подход позволяет реализовать полноценное VR-взаимодействие без сложной логики низкоуровневого отслеживания состояний контроллера.
hand-controls, который автоматически подбирает подходящий
контроллер.<a-scene>), чтобы
обработка работала глобально для всех контроллеров.axismove высокая, поэтому важно
оптимизировать обработку, чтобы не перегружать рендеринг.AFRAME.registerComponent('axismove-logger', {
init: function() {
this.el.addEventListener('axismove', (evt) => {
const [x, y] = evt.detail.axis;
if (Math.abs(x) > 0.1 || Math.abs(y) > 0.1) {
console.log('Активное движение:', x, y);
}
});
}
});
Такой фильтр исключает мелкие шумы стика и делает взаимодействие более предсказуемым.
Использование событий buttondown, buttonup
и axismove совместно с компонентами контроллеров позволяет
создавать интерактивные VR-приложения, где каждая
кнопка и ось управляются напрямую через объект события. Это делает
возможным как простые действия (нажатие кнопки), так и сложные механики
(перемещение, вращение, захват объектов) без необходимости обращаться к
низкоуровневым API WebXR.