Директива Angualr JS вызывается несколько раз с помощью ui-router - PullRequest
1 голос
/ 04 мая 2020

У меня есть HTML аудиоплеер, вызываемый как часть директивы в AngularJS. На странице refre sh проигрыватель работает отлично - я могу установить источник и воспроизводить аудио - консоль записывает это: enter image description here Однако, если я перехожу к другому состоянию в моем приложении и ТО загружаю / играю аудио, 2 экземпляра аудио начинают играть. Если я посещу 4 состояния перед воспроизведением, будет воспроизводиться 4 экземпляра звука! Консоль регистрирует это: enter image description here

Почему аудиопроигрыватель запускается снова и снова? Как я могу сохранить его активным при перемещении между состояниями? Я не хочу уничтожать его и повторно инициализировать каждый раз, когда я меняю состояние, что приведет к прерыванию воспроизведения звука.

Вот соответствующий код. По сути, нижний колонтитул вида. html содержит директиву и игрока и включается каждым состоянием.

index. html:

  ...
  <div style="clear:both"></div>

  <div ui-view="footer"></div>
</body>

app. js:

.state('audiolist', {
      url: '/audiolist/',
      views: {
        sideNav: {
          templateUrl: 'views/sideNav.html',
          controller: 'sideNavController'
        },
        header: {
          templateUrl: 'views/header.html',
          controller: 'headerController'
        },
        content: {
          templateUrl: 'views/list.main.html',
          controller: 'listController as content'
        },
        footer: {
          templateUrl: 'views/footer.html',
          controller: 'apController as ap'
        }
      })
    ...
    .state('saveditems', {
      url: '/saveditems/',
      views: {
        sideNav: {
          templateUrl: 'views/sideNav.html',
          controller: 'sideNavController'
        },
        header: {
          templateUrl: 'views/header.html',
          controller: 'headerController'
        },
        content: {
          templateUrl: 'views/saveditems.main.html',
          controller: 'savedItemsController as content'
        },
        footer: {
          templateUrl: 'views/footer.html',
          controller: 'apController as ap'
        }
      }
...

нижний колонтитул. html

    <div class="audioplayer">
      <!-- Audio Player -->
      <hls-player id="player" playlist="{{ap.tracks}}"></hls-player>
...

директивы / hlsPlayer. js

module.directive('hlsPlayer', function ($window, $templateRequest, $compile, $http, $rootScope) {
return {
    restrict: 'AE',
    link: function ($scope, element, attrs) {
        $templateRequest("views/playerTemplate.html").then(function (html) {
        // player functions 
        ... 
        // play function 
           ...
           console.log("manifest loaded, found " + data.qualities + " quality level");
           console.log("audio loaded and playing");
    ...

playerTemplate. html

...
 <audio autobuffer preload="metadata" src="" id="radio" class="hidden" preload="none"></audio>
...

Ответы [ 2 ]

1 голос
/ 04 мая 2020

При изменении состояния AngularJS снова инициализирует контроллеры. Директива hlsPlayer имеет ту же область действия, что и контроллер. Так что link вызывается снова.

Вы можете использовать $on "$destroy" для завершения работы директивы sh, чтобы изящно остановить игрока.

element.on('$destroy', function () {
     // stop/destroy here the player
});

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

0 голосов
/ 08 мая 2020

Мое решение, которое не сработало бы в каждом случае, состояло в том, чтобы убрать самого игрока HTML5 из шаблона директивы и поместить его в главный индекс. html страница. Это хорошо работает для постоянного звука в Angular, и я по-прежнему могу загружать, контролировать и отображать временную шкалу, как и раньше, ссылаясь на этот аудиоэлемент. Например:

index. html:

<audio id="mediaPlayer" autobuffer preload="metadata" src="" id="radio" class="hidden" preload="none"></audio>

Директива:

return {
    restrict: 'AE',
    link: function ($scope, element, attrs) {
 $templateRequest("views/playerTemplate.html").then(function (html) {
            var template = angular.element(html);

            element.html(template);
            $compile(element.contents())($scope);

            var elem = angular.element(document.querySelector('#mediaPlayer'));
            var audio = elem[0];

            $scope.play = function () {               
                    audio.play();
                }

playerTemplate. html (используйте $ scope vars и функции из директивы to управлять игроком)

<a type="button" ng-click="played=!played; played ? play() :stop();"><i
                ng-class="played?'nav-btn-play fa fa-pause-circle-o':'nav-btn-play fa fa-play-circle-o'"></i></a>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...