Youtube iframe Api и маршрут Angularjs

Я столкнулся с проблемой при использовании Youtube Iframe Api с angularjs.

Я думаю, проблема в вызове функции onYouTubeIframeAPIReady.

Я использую angularjs с маршрутами, и функция не срабатывает при изменении маршрута, однако, когда я нажимаю F5, все в порядке, проигрыватель загружается.

Есть ли способ заставить работать angularjs с маршрутами и API YouTube?

Мне не удалось добавить больше файла в код, но «pageX.htm» выглядит так:

<button ng-click="video()">Create</button>
<div youtube-player id="test-playerX" ></div>

И есть код для "index.htm"

<!DOCTYPE html>
<html ng-app="sc">
  <body>

    Homepage - <a href="#page1">Page1</a> - <a href="#page2">Page2</a>

    <div ng-view></div>

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
    <script src="https://code.angularjs.org/1.4.3/angular-route.min.js"></script>
    
    <script>
      var sc = angular.module('sc', ['ngRoute']);

      sc.config(['$routeProvider', function($routeProvider) {
        $routeProvider
          .when('/page1', {
            templateUrl: 'page1.htm'
          })
          .when('/page2', {
            templateUrl: 'page2.htm'
          })
      }]);

            // Run
      sc.run(['$rootScope', function($rootScope) {

                var tag = document.createElement('script');

                // This is a protocol-relative URL as described here:
                //     http://paulirish.com/2010/the-protocol-relative-url/
                // If you're testing a local page accessed via a file:/// URL, please set tag.src to
                //     "https://www.youtube.com/iframe_api" instead.
                tag.src = "http://www.youtube.com/iframe_api";
                var firstScriptTag = document.getElementsByTagName('script')[0];
                firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
            }]);


      sc.service('youtubePlayerApi', ['$window', '$rootScope', '$log', function ($window, $rootScope, $log) {
        var service = $rootScope.$new(true);

        // Youtube callback when API is ready
        $window.onYouTubeIframeAPIReady = function () {
            $log.info('Youtube API is ready');
            service.ready = true;
            service.createPlayer();
        };

        service.ready = false;
        service.playerId = null;
        service.player = null;
        service.videoId = "sGPrx9bjgC8";
        service.playerHeight = '390';
        service.playerWidth = '640';

        service.bindVideoPlayer = function (elementId) {
            $log.info('Binding to player ' + elementId);
            service.playerId = elementId;
        };

        service.createPlayer = function () {
            $log.info('Creating a new Youtube player for DOM id ' + this.playerId + ' and video ' + this.videoId);
            return new YT.Player(this.playerId, {
                height: this.playerHeight,
                width: this.playerWidth,
                videoId: this.videoId
            });
        };

        service.loadPlayer = function () {
            // API ready?
            if (this.ready && this.playerId && this.videoId) {
                if(this.player) {
                    this.player.destroy();
                }

                this.player = this.createPlayer();
            }
        };

        return service;
      }]);

      sc.directive('youtubePlayer', ['youtubePlayerApi', function (youtubePlayerApi) {
          return {
              restrict:'A',
              link:function (scope, element) {
                  youtubePlayerApi.bindVideoPlayer(element[0].id);
              }
          };
      }]);
      
      sc.controller('replaycontroller', function ($scope,youtubePlayerApi) {
              $scope.video = function () {
                youtubePlayerApi.createPlayer();
                console.log("test");
              }

          });
    </script>


  </body>
</html>

Любая помощь приветствуется :)

[EDIT]: я обновил код, чтобы протестировать функцию createPlayer и подтвердить, что проигрыватель работает при смене страниц.


person djutopie    schedule 05.08.2015    source источник


Ответы (3)


Как говорит Каран Капур в последнем комментарии, лучший способ использовать API YouTube с angularjs — использовать github. com/brandly/angular-youtube-embed

person djutopie    schedule 02.09.2015

Хорошо, я нашел решение, оно далеко не самое чистое, но работает.

Допускаю, что в контроллере при смене маршрутов уже инициализируется апи ютуба. Таким образом, контроллер просто создает игрока.

Когда запрашивается F5 или первая загрузка, мы должны запустить onYouTubeIframeAPIReady, чтобы создать экземпляр проигрывателя.

Вот код:

<!DOCTYPE html>
<html ng-app="sc">
  <body>

    Homepage - <a href="#page1">Page1</a> - <a href="#page2">Page2</a>

    <div ng-view></div>

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
    <script src="https://code.angularjs.org/1.4.3/angular-route.min.js"></script>
    
    <script>
      var sc = angular.module('sc', ['ngRoute']);

      sc.config(['$routeProvider', function($routeProvider) {
        $routeProvider
          .when('/page1', {
            templateUrl: 'page1.htm',
            controller: 'replaycontroller'
          })
          .when('/page2', {
            templateUrl: 'page2.htm'
          })
      }]);

            // Run
      sc.run(['$rootScope', function($rootScope) {
               var tag = document.createElement('script');

                // This is a protocol-relative URL as described here:
                //     http://paulirish.com/2010/the-protocol-relative-url/
                // If you're testing a local page accessed via a file:/// URL, please set tag.src to
                //     "https://www.youtube.com/iframe_api" instead.
                tag.src = "http://www.youtube.com/iframe_api";
                var firstScriptTag = document.getElementsByTagName('script')[0];
                firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
               
            }]);


      sc.service('youtubePlayerApi', ['$window', '$rootScope', '$log', function ($window, $rootScope, $log) {
        var service = $rootScope.$new(true);

        // Youtube callback when API is ready
        $window.onYouTubeIframeAPIReady = function () {
            $log.info('Youtube API is ready');
            service.ready = true;
            service.createPlayer();
        };

        service.ready = false;
        service.playerId = null;
        service.player = null;
        service.videoId = "sGPrx9bjgC8";
        service.playerHeight = '390';
        service.playerWidth = '640';

        service.getStatus = function () {
          return service.ready;
        };

        service.bindVideoPlayer = function (elementId) {
            $log.info('Binding to player ' + elementId);
            service.playerId = elementId;
        };

        service.createPlayer = function () {
            $log.info('Creating a new Youtube player for DOM id ' + this.playerId + ' and video ' + this.videoId);
            return new YT.Player(this.playerId, {
                height: this.playerHeight,
                width: this.playerWidth,
                videoId: this.videoId
            });
        };

        service.loadPlayer = function () {
            // API ready?
            if (this.ready && this.playerId && this.videoId) {
                if(this.player) {
                    this.player.destroy();
                }

                this.player = this.createPlayer();
            }
        };

        return service;
      }]);

      sc.directive('youtubePlayer', ['youtubePlayerApi', function (youtubePlayerApi) {
          return {
              restrict:'A',
              link:function (scope, element) {
                  youtubePlayerApi.bindVideoPlayer(element[0].id);
              }
          };
      }]);

      sc.controller('replaycontroller', function ($scope,youtubePlayerApi) {
        if (youtubePlayerApi.getStatus() == true) {
          youtubePlayerApi.bindVideoPlayer("test-player1");
          youtubePlayerApi.createPlayer();
        }
      });

        
    </script>


  </body>
</html>

person djutopie    schedule 05.08.2015
comment
Как вы его использовали в итоге? Как я могу использовать его с несколькими видео YouTube на одной странице? Таким образом, в основном у меня будут все идентификаторы видео YouTube в массиве, и я хотел бы инициализировать их на странице как видео в ng-repeat, а затем фиксировать события для каждого из них по отдельности. Любая идея, как это можно сделать? - person Karan Kapoor; 26.08.2015
comment
Привет, наконец, я больше не использую youtube api, а тег youtube iframe... Действительно непросто реализовать youtube api в приложении angularjs. Извините, я не помог - person djutopie; 28.08.2015
comment
Нашел лучший способ сделать это. Если вы хотите реализовать это самостоятельно, используйте Google iFrame API. или используйте репозиторий angular github.com/brandly/angular-youtube-embed . Я использовал последний. :) - person Karan Kapoor; 31.08.2015
comment
Благодаря вам я попробую, как только смогу - person djutopie; 02.09.2015

У меня была та же проблема, и я сделал сброс скрипта до нуля, а затем снова установил его:

init() {
    if (window["YT"]) {
        window["YT"] = null;
        this.tag = document.createElement("script");
        this.tag.src = "https://www.youtube.com/iframe_api";
        this.firstScriptTag = document.getElementsByTagName("script")[0];
        this.firstScriptTag.parentNode.insertBefore(this.tag, this.firstScriptTag);
    }
    this.tag = document.createElement("script");
    this.tag.src = "https://www.youtube.com/iframe_api";
    this.firstScriptTag = document.getElementsByTagName("script")[0];
    this.firstScriptTag.parentNode.insertBefore(this.tag, this.firstScriptTag);
    window["onYouTubeIframeAPIReady"] = () => this.startVideo();
}
person MatteoMatteoMatteo    schedule 18.09.2020