Использование Adobe Edge Animate с AngularJS и AngularUI Router

Сейчас я работаю над проектом, который будет включать несколько анимаций, созданных с помощью Adobe Edge Animate, в одно приложение AngularJS. Идея состоит в том, что эти анимации будут выступать в качестве визуальных эффектов для игры, а я буду управлять композицией на основе информации, получаемой от игрока. Потребовались некоторые эксперименты, чтобы добраться до этой стадии, но все это работает отлично.

Мои проблемы начинаются всякий раз, когда игрок решает выйти из текущего вида и получить к нему доступ во второй раз. По какой-то причине это вызывает проблему с API Adobe Edge Animate Javascript, и композиция не загружается.

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

Uncaught TypeError: Cannot read property 'stage' of undefined    edge.5.0.1.js:4872
Uncaught TypeError: Cannot read property 'stage' of undefined    edge.5.0.1.js:4519

В настоящее время я загружаю композицию прямо из контроллера следующим образом...

.controller('GameTest', function($scope, $state) {
    AdobeEdge.loadComposition('edge-animate/GameTest', 'GameTest', {
      scaleToFit: "width",
      centerStage: "none",
      minW: "0",
      maxW: "undefined",
      width: "2048px",
      height: "1134px"
    }, {dom: [ ]}, {dom: [ ]});
})

Я также отключил кеширование для этого состояния...

.state('game-test', {
  cache: false,
  url: "/games/test",
  controller: 'GameTest',
  templateUrl: 'templates/games/test.html'
})

Все предложения приветствуются и ценят любую помощь!

Спасибо

Обновление: я разработал решение! С надеждой...

Эта проблема, похоже, будет решена, если браузер снова обработает содержимое соответствующего *_edge.js. Так как они вводятся в <head> всякий раз, когда AdobeEdge.loadComposition(...) вызывается (через yepnope), и, по-видимому, нет никакого способа попросить yepnope перезагрузить внедренный Javascript, я написал небольшой сервис для Angular, который я могу использовать для обработки этого вместо стандартного AdobeEdge.loadComposition(...) функция. По сути, это обертка, которая сделает соответствующие проверки заранее.

.service('$AdobeEdge', function() {
  var head = document.getElementsByTagName('head')[0],
    scripts = head.getElementsByTagName('script');

  return { 
    loadComposition: function(projectPrefix, compId, opts, preloaderDOM, downLevelStageDOM) {
      // Determine the filename for our project
      var projectFile = projectPrefix + '_edge.js';
      var newScript = null;

      // Iterate through each script tag in the header to search for our file
      angular.forEach(scripts, function(script, index, scripts) {

        // Does the script src tag end with our project filename?
        if (script.src.substr(script.src.length - projectFile.length) == projectFile) {

          // It's already loaded! Let's go about removing it and injecting a fresh script tag...
          script.remove();
          newScript = document.createElement('script');
          newScript.setAttribute('type', 'text/javascript');
          newScript.setAttribute('src', script.src);
          head.insertBefore(newScript, scripts[0]);

          // Let's also delete the composition within the Adobe Edge API so that events
          // like 'compositionReady' are fired again when we call loadComposition()
          delete AdobeEdge.compositions[compId];
        }
      });

      // Ultimately we always need to call loadComposition() no matter what
      AdobeEdge.loadComposition(projectPrefix, compId, opts, preloaderDOM, downLevelStageDOM);
    }
  }
})

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

.controller('GameTest', function($scope, $state, $AdobeEdge) {
  $AdobeEdge.loadComposition('edge-animate/GameTest', 'GameTest', {
    scaleToFit: "width",
    centerStage: "none",
    minW: "0",
    maxW: "undefined",
    width: "2048px",
    height: "1134px"
  }, {dom: [ ]}, {dom: [ ]});
});

Пока это работает отлично! Я буду использовать его для создания остальных игр в нашем проекте и публиковать любые возникающие проблемы.

Надеюсь, это спасет кого-то еще много душевной боли!

1 ответ

Ответ Роба Синтона:

Эта проблема, похоже, будет решена, если браузер снова обработает содержимое соответствующего *_edge.js. Так как они вводятся в <head> всякий раз, когда AdobeEdge.loadComposition(...) вызывается (через yepnope), и, по-видимому, нет никакого способа попросить yepnope перезагрузить внедренный Javascript, я написал небольшой сервис для Angular, который я могу использовать для обработки этого вместо стандартного AdobeEdge.loadComposition(...) функция. По сути, это обертка, которая сделает соответствующие проверки заранее.

.service('$AdobeEdge', function() {
  var head = document.getElementsByTagName('head')[0],
    scripts = head.getElementsByTagName('script');

  return { 
    loadComposition: function(projectPrefix, compId, opts, preloaderDOM, downLevelStageDOM) {
      // Determine the filename for our project
      var projectFile = projectPrefix + '_edge.js';
      var newScript = null;

      // Iterate through each script tag in the header to search for our file
      angular.forEach(scripts, function(script, index, scripts) {

        // Does the script src tag end with our project filename?
        if (script.src.substr(script.src.length - projectFile.length) == projectFile) {

          // It's already loaded! Let's go about removing it and injecting a fresh script tag...
          script.remove();
          newScript = document.createElement('script');
          newScript.setAttribute('type', 'text/javascript');
          newScript.setAttribute('src', script.src);
          head.insertBefore(newScript, scripts[0]);

          // Let's also delete the composition within the Adobe Edge API so that events
          // like 'compositionReady' are fired again when we call loadComposition()
          delete AdobeEdge.compositions[compId];
        }
      });

      // Ultimately we always need to call loadComposition() no matter what
      AdobeEdge.loadComposition(projectPrefix, compId, opts, preloaderDOM, downLevelStageDOM);
    }
  }
})

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

.controller('GameTest', function($scope, $state, $AdobeEdge) {
  $AdobeEdge.loadComposition('edge-animate/GameTest', 'GameTest', {
    scaleToFit: "width",
    centerStage: "none",
    minW: "0",
    maxW: "undefined",
    width: "2048px",
    height: "1134px"
  }, {dom: [ ]}, {dom: [ ]});
});

Пока это работает отлично! Я буду использовать его для создания остальных игр в нашем проекте и публиковать любые возникающие проблемы.

Надеюсь, это спасет кого-то еще много душевной боли!

Другие вопросы по тегам