Babylon.js предоставляет мощный инструмент для работы с событиями через класс Observable. Observable — это шаблон проектирования, который позволяет объектам уведомлять подписчиков о произошедших событиях. В контексте 3D-сцен это особенно удобно для реагирования на взаимодействие с объектами, изменение состояния сцены или управление анимацией.
Ключевые свойства Observable:
observers — массив подписчиков события.add(callback) — метод для добавления подписчика.remove(callback) — удаление подписчика.notifyObservers(eventData) — уведомление всех
подписчиков с передачей данных события.clear() — удаление всех подписчиков.Пример создания Observable:
const onCubeClic ked = new BABYLON.Observable();
Подписка на событие:
onCubeClicked.add((mesh) => {
console.log("Клик по объекту:", mesh.name);
});
Вызов уведомления:
onCubeClicked.notifyObservers(cubeMesh);
Каждый объект сцены в Babylon.js, например Mesh, Camera, Light, может иметь свои события на базе Observable. Основные встроенные Observables:
onDisposeObservable — вызывается при удалении
объекта.onPointerObservable — реагирует на действия мыши и
касания.onBeforeRenderObservable и
onAfterRenderObservable — события перед и после рендера
сцены.onReadyObservable — для готовых к использованию
объектов или ассетов.Пример использования onPointerObservable:
scene.onPointerObservable.add((pointerInfo) => {
switch (pointerInfo.type) {
case BABYLON.PointerEventTypes.POINTERDOWN:
console.log("Нажатие на сцену");
break;
case BABYLON.PointerEventTypes.POINTERUP:
console.log("Отпускание кнопки мыши");
break;
}
});
Тип события определяется константами PointerEventTypes,
что упрощает фильтрацию действий.
Для крупномасштабных приложений удобно создать централизованную событийную шину, которая объединяет все Observables. Такой подход облегчает управление взаимодействием между различными модулями сцены.
Пример структуры событийной шины:
class EventBus {
constructor() {
this.events = {};
}
createEvent(eventName) {
if (!this.events[eventName]) {
this.events[eventName] = new BABYLON.Observable();
}
return this.events[eventName];
}
subscribe(eventName, callback) {
if (!this.events[eventName]) {
this.createEvent(eventName);
}
this.events[eventName].add(callback);
}
emit(eventName, data) {
if (this.events[eventName]) {
this.events[eventName].notifyObservers(data);
}
}
unsubscribe(eventName, callback) {
if (this.events[eventName]) {
this.events[eventName].remove(callback);
}
}
clearEvent(eventName) {
if (this.events[eventName]) {
this.events[eventName].clear();
}
}
}
Использование шины:
const bus = new EventBus();
// Подписка на событие
bus.subscribe("cubeClicked", (mesh) => {
mesh.material.diffuseColor = new BABYLON.Color3(1, 0, 0);
});
// Генерация события
cubeMesh.actionManager = new BABYLON.ActionManager(scene);
cubeMesh.actionManager.registerAction(
new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPickTrigger, () => {
bus.emit("cubeClicked", cubeMesh);
})
);
Observable позволяет легко интегрировать события с анимациями и пользовательским интерфейсом. Например, можно реагировать на клики и запускать анимацию движения камеры:
bus.subscribe("cameraMove", (targetPosition) => {
BABYLON.Animation.CreateAndStartAnimation(
"camMove",
camera,
"position",
60,
120,
camera.position,
targetPosition,
BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT
);
});
// Генерация события для перемещения камеры
bus.emit("cameraMove", new BABYLON.Vector3(5, 10, -5));
Такой подход позволяет отделить логику событий от самой сцены и упрощает расширение функционала.
onBeforeRenderObservable) использовать минимальное
количество подписчиков и фильтровать действия по необходимости.Использование Observable и событийной шины делает архитектуру Babylon.js-приложений модульной, управляемой и легко масштабируемой.