Доступ к сущности и сцене из компонента

В A-Frame каждый компонент работает в контексте сущности (entity) и сцены (scene). Понимание того, как получать доступ к этим объектам, критично для создания интерактивных и динамических VR-приложений.

Сущность (entity) и контекст компонента

Каждый компонент в A-Frame привязан к конкретной сущности. Ссылка на эту сущность доступна через свойство this.el.

Пример:

AFRAME.registerComponent('log-position', {
  init: function () {
    console.log('Сущность:', this.el);
    console.log('Позиция:', this.el.getAttribute('position'));
  }
});

Здесь this.el возвращает DOM-элемент сущности, к которой привязан компонент. С помощью методов getAttribute и setAttribute можно читать и изменять свойства сущности, такие как позиция, вращение, масштаб, материалы и другие атрибуты.

Взаимодействие с другими компонентами сущности

Компоненты могут взаимодействовать друг с другом, получая доступ к другим компонентам той же сущности через this.el.components.

Пример:

AFRAME.registerComponent('sync-scale', {
  init: function () {
    const materialComp = this.el.components.material;
    if (materialComp) {
      console.log('Цвет материала:', materialComp.color);
    }
  }
});

Важный момент: доступ к компоненту через this.el.components.<componentName> возможен только после того, как компонент был инициализирован. Для гарантии правильного порядка используется событие loaded:

this.el.addEventListener('loaded', () => {
  const geometryComp = this.el.components.geometry;
  console.log('Тип геометрии:', geometryComp.data.primitive);
});

Доступ к сцене

Сцена в A-Frame представлена элементом <a-scene> и является корневым контейнером всех сущностей. Доступ к сцене из компонента осуществляется через свойство this.el.sceneEl.

Пример:

AFRAME.registerComponent('scene-info', {
  init: function () {
    console.log('Сцена:', this.el.sceneEl);
    console.log('Количество сущностей в сцене:', this.el.sceneEl.children.length);
  }
});

С помощью this.el.sceneEl можно:

  • Найти другие сущности по id или class:
const otherEntity = this.el.sceneEl.querySelector('#box1');
  • Добавлять новые сущности динамически:
const box = document.createElement('a-box');
box.setAttribute('position', { x: 0, y: 1, z: -3 });
this.el.sceneEl.appendChild(box);
  • Подписываться на события сцены:
this.el.sceneEl.addEventListener('enter-vr', () => {
  console.log('Пользователь вошёл в VR');
});

Методы поиска сущностей

Помимо стандартного querySelector, A-Frame предоставляет утилиты:

  • this.el.sceneEl.querySelectorAll('[component-name]') — выбор всех сущностей с указанным компонентом.
  • AFRAME.scenes[0] — доступ к первой сцене на странице (полезно при мультисценовых приложениях).

Пример динамического взаимодействия:

AFRAME.registerComponent('highlight-targets', {
  init: function () {
    const targets = this.el.sceneEl.querySelectorAll('.target');
    targets.forEach(target => {
      target.setAttribute('material', 'color', 'yellow');
    });
  }
});

Управление состоянием сущности через компоненты

Компоненты могут изменять атрибуты сущности напрямую:

this.el.setAttribute('position', { x: 2, y: 3, z: -5 });
this.el.setAttribute('rotation', { x: 0, y: 45, z: 0 });

А также использовать tick для постоянного обновления состояния:

AFRAME.registerComponent('rotate-continuous', {
  tick: function (time, timeDelta) {
    const rotation = this.el.getAttribute('rotation');
    this.el.setAttribute('rotation', {
      x: rotation.x,
      y: rotation.y + timeDelta * 0.05,
      z: rotation.z
    });
  }
});

Особенности при работе с асинхронными событиями

Многие действия в A-Frame происходят после полной загрузки сцены или ресурсов. Для надежного доступа к сущности или сцене используется событие loaded:

this.el.addEventListener('loaded', () => {
  const scene = this.el.sceneEl;
  console.log('Сцена загружена, готово к манипуляции');
});

Аналогично можно использовать события компонентов, например model-loaded для <a-entity> с 3D-моделью.

Итоговые рекомендации

  • this.el — доступ к текущей сущности компонента.
  • this.el.sceneEl — доступ к сцене.
  • this.el.components — доступ к другим компонентам той же сущности.
  • querySelector и querySelectorAll — поиск других сущностей в сцене.
  • Событие loaded гарантирует, что все элементы и компоненты уже доступны.

Эти инструменты позволяют строить динамичные, интерактивные VR-сцены, где компоненты не ограничиваются собственными данными, а могут управлять всей сценой и взаимодействовать с другими сущностями.