В A-Frame компоненты являются основным механизмом расширения функциональности сцены и объектов. Каждый компонент может взаимодействовать с другими компонентами, получать доступ к данным сцены и управлять поведением сущностей. Ключевым аспектом является доступ к системам — глобальным объектам, которые предоставляют общий функционал для группы компонентов.
Система в A-Frame — это объект, зарегистрированный через
AFRAME.registerSystem, который предоставляет
централизованное управление данными или поведением,
общими для нескольких компонентов. Системы обычно используются для:
Пример регистрации системы:
AFRAME.registerSystem('score', {
schema: { total: { type: 'int', default: 0 } },
init: function () {
console.log('Система Score инициализирована');
},
addPoints: function (points) {
this.data.total += points;
console.log('Общий счет:', this.data.total);
}
});
Система score хранит общий счет и предоставляет метод
addPoints для обновления.
Компоненты могут получать доступ к любой системе, используя метод
this.el.sceneEl.systems. Это объект, где ключи —
это имена зарегистрированных систем.
Пример использования системы в компоненте:
AFRAME.registerComponent('coin', {
schema: { value: { type: 'int', default: 1 } },
init: function () {
this.scoreSystem = this.el.sceneEl.systems['score'];
},
collect: function () {
if (this.scoreSystem) {
this.scoreSystem.addPoints(this.data.value);
this.el.parentNode.removeChild(this.el);
}
}
});
Здесь компонент coin при сборе монеты обращается к
системе score и добавляет очки.
Важно:
this.el.sceneEl.systems['имя_системы'] возвращает
систему, уже инициализированную сценой, поэтому доступ
к ней возможен после init компонента.
init() — инициализация компонента;
можно сохранять ссылку на систему.update() — обновление данных
компонента; можно взаимодействовать с системой при изменении
свойств.tick() — вызов на каждом кадре;
допустимо постоянное обращение к системе.remove() — очистка ресурсов; можно
уведомлять систему об удалении компонента.Пример использования жизненного цикла:
AFRAME.registerComponent('health', {
schema: { max: 100, current: 100 },
init: function () {
this.healthSystem = this.el.sceneEl.systems['health'];
this.healthSystem.registerEntity(this.el);
},
tick: function (time, delta) {
if (this.data.current <= 0) {
this.healthSystem.deregisterEntity(this.el);
this.el.parentNode.removeChild(this.el);
}
}
});
Система может быть точкой синхронизации для множества компонентов. Например, несколько компонентов могут изменять один и тот же ресурс:
AFRAME.registerSystem('music', {
init: function () {
this.isPlaying = false;
},
play: function () { this.isPlaying = true; },
stop: function () { this.isPlaying = false; }
});
AFRAME.registerComponent('button-play', {
init: function () {
this.musicSystem = this.el.sceneEl.systems['music'];
this.el.addEventListener('click', () => {
this.musicSystem.play();
});
}
});
AFRAME.registerComponent('button-stop', {
init: function () {
this.musicSystem = this.el.sceneEl.systems['music'];
this.el.addEventListener('click', () => {
this.musicSystem.stop();
});
}
});
В этом примере две кнопки управляют одной системой, что обеспечивает централизованное управление состоянием музыки.
if (this.el.sceneEl.systems['имя'])).AFRAME.systemsПомимо обращения через el.sceneEl.systems, можно
использовать глобальный объект A-Frame:
const scoreSystem = AFRAME.scenes[0].systems['score'];
scoreSystem.addPoints(10);
Этот способ позволяет получать доступ к системе без привязки к конкретной сущности, но менее безопасен для многосценных проектов.
this.el.sceneEl.systems.init().Эти подходы обеспечивают чистую архитектуру сцены и позволяют создавать масштабируемые VR-приложения на A-Frame.