Я работаю над игрой, использующей angular.js для ui и класса игрового движка.
Из-за конфликтов между классом игрового движка и библиотекой углового материала я должен загрузить игровой движок в порядок после углового.
После инициализации игрового движка он отправляет пользовательское событие dom "clientReady" с двумя объектами, которые мне нужно получить в моих угловых контроллерах.
Итак, на app.run я инициализируйте эти 2 объекта в корневой области следующим образом:
app.run(function($rootScope) {
$rootScope.engine = {};
$rootScope.editor = {};
document.addEventListener('clientReady', function(e) {
$rootScope.$apply(function() {
$rootScope.engine = e.detail.engine;
$rootScope.editor = e.detail.editor;
});
});
});
Теперь в моих контроллерах я пытаюсь установить области действия:
$scope.player = $rootScope.engine.player;
Это не работает, конечно, потому что событие "clientReady" происходит позднее после углового инициализации, а корневой код не существует, когда он запускает контроллер.
Есть ли способ справиться с этим? Мне интересно, могу ли я как-то запустить контроллеры после события dom.
С уважением, Стефан
Вы не можете "запустить" контроллер. Вы можете перейти к представлению, и он запустит его контроллер и свяжет область действия контроллера с соответствующим представлением.
Поэтому, если вы хотите, чтобы это событие слушалось всегда, вы должны сделать это в BodyController. Но если вы хотите прослушать это событие только на определенных экранах, возможно, вы должны просто сделать это на app.run
app.controller('BodyController', function($rootScope) {
$document.addEventListener('clientReady', function(e) {
// Decide based on view when you want to change initialize the game or not
if($location.path == '/login') {
// don't let the user init as he/she is not logged in
} else {
//init
// Store e in a service or $rootScope. I'd pick a service to do this as I wouldn't want to clutter my $rootScope
GameService.save(e);
// Handle transition to the new path
$location.path('/something');
}
});
})
Или, если вы хотите прослушать только одно или несколько просмотров. 1. Слушайте событие clientReady на одном или нескольких ваших представлениях (при условии, что это событие инициализируется только один раз)
Итак, предположим, что ваш домашний/стандартный вид - '/'. Затем в HomeController вы выполните следующее:
app.controller('MainCtrl', function($scope, $document) {
$document.addEventListener('clientReady', function(e) {
// Store e in a service or $rootScope. I'd pick a service to do this as I wouldn't want to clutter my $rootScope
GameService.save(e);
// Goto to View/Controller that needs e
$location.path('/something');
});
}
isInitialized()
возвращает true ТОЛЬКО при clientReady
события clientReady
. Если isInitialized() return false, then the $location will be changed and execution of GameCtrl will stop (because of
заявления return)
app.controller('GameCtrl', function($scope, GameService, $location) {
if(!GameService.isInitialized()) {
$location.path('/home'); // or to any other route you deem fit
// Instead of redirecting, you can handle this gracefully on this view too. But I think that'll take much more effort.
return; //Important so that the controller is not processed any further
}
// This is where the magic happens!
$scope.engine = GameService.getEngine();
$scope.editor = GameService.getEditor();
}
GameService
- это место, где хранится игровой движок и другой объект, заданный клиентом.
angular.module('myApp').service('GameService', function() {
// AngularJS will instantiate a singleton by calling "new" on this function
this.getEngine = function() {
// Logic
}
this.getEditor = function () {
// Logic
}
this.isInitialized = function () {
// Logic
}
};
Вы можете использовать $broadcast & $on
для общения.
document.addEventListener('clientReady', function(e) {
var objData = {};
objData.engine = e.detail.engine;
objData.editor = e.detail.editor;
$rootScope.$broadcast('updated-data',{objData : objData});
});
В контроллере,
$scope.$on('updated-data',function(event,eveneData){
console.log(eveneData);
})