Youtube iframe Api 和 Angularjs 路由

Youtube iframe Api and Angularjs route

我遇到与 angularjs 一起使用的 Youtube Iframe Api 的问题。

我认为问题出在 "onYouTubeIframeAPIReady" 函数的调用上。

我将 angularjs 与路线一起使用,当路线改变时该功能不会触发,但是当我按下 F5 时播放器加载正常。

有没有办法让 angularjs 与路线和 youtube API 一起工作?

我没能在代码中添加更多文件,但 "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>

感谢任何帮助:)

[编辑]:我更新了代码以测试函数 createPlayer 并确认播放器在更改页面时正常工作

好的,我找到了一个解决方案,它远不是最干净的,但它有效。

我承认当你在控制器中改变路线时,youtube api 已经被初始化了。所以控制器只是创建播放器。

当 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>

正如 Karan Kapoor 在最后一条评论中所说,将 youtube api 与 angularjs 一起使用的最佳方式是使用 github.com/brandly/angular-youtube-embed

我遇到了同样的问题,我所做的是将脚本重置为 null,然后重新设置它:

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();
}