AngularJS 和 Youtube,在视频播放完毕后调用脚本

AngularJS and Youtube, call a script when video finishes playing

我正在尝试在 youtube 播放完视频后调用一个函数。 我设置了这样的视图:

<div class="row">
    <div class="col-md-6">

        <div id="player" ts-video-player></div>

    </div>
</div>

然后我决定设置这样的指令:

.directive('tsVideoPlayer', ['$state', function ($state) {


    // autoplay video
    function onPlayerReady(event) {
        console.log('autoplay');

        event.target.playVideo();
    }

    // when video ends
    function onPlayerStateChange(event) {
        if (event.data === 0) {
            console.log('finsihed');

            alert('done');
        }
    }

    return {
        restrict: 'A',
        link: function (scope, element) {

            console.log('set up player');
            console.log(element.attr('id'));

            function onYouTubePlayerAPIReady() {

                console.log('Creating player');

                var player = new YT.Player(element.attr('id'), {
                    height: '390',
                    width: '640',
                    videoId: 'GE2BkLqMef4',
                    events: {
                        'onReady': onPlayerReady,
                        'onStateChange': onPlayerStateChange
                    }
                });
            }
        }
    }
}])

我已将此脚本包含在 index.html 文件中:

<script src="http://www.youtube.com/player_api"></script>

但是没有任何反应。 我的控制台日志显示 'setting up video player' 和播放器 ID,但 onYouTubePlayerAPIReady 从未被调用。

有人可以帮我吗?

原因可能是因为您定义的函数位于链接函数闭包的指令中。 YouTube api 无法访问该方法。您需要将其放入 window 对象。您可以通过以下几种方式:

1) 创建全局函数并通过事件通知

就在你的 body 标签结束之前,将函数放在全局范围内并获取 angular rootScope 元素并广播一个事件:

<script>
  function onYouTubePlayerAPIReady(){
    angular.element(document).ready(function(){
       var rootScope = angular.element(document).injector().get('$rootScope');
       rootScope.$broadcast('onYouTubePlayerAPIReady');
    });
  }
</script>
<script src="http://www.youtube.com/player_api"></script>

并在您的指令中订阅此活动。

.directive('tsVideoPlayer', [function () {


    // autoplay video
    //....

    return {
        restrict: 'A',
        link: function (scope, element) {
           //....
            scope.$on('onYouTubePlayerAPIReady', function() {
              console.log('Creating player');
               var player = new YT.Player(element.attr('id'), {
                  .....
                });
            });
        }
    }
}]);

Demo


2) 检查指令本身的状态

另一种方法是检查 YT 对象及其 loaded 状态并执行必要的操作。

.directive('tsVideoPlayer', ['$window', function ($window) {

    return {
        restrict: 'A',
        link: function (scope, element) {
            console.log(YT.loaded);

            if (!YT) {
                console.log('playerNotLoaded');
                $window.onYouTubePlayerAPIReady = onPlayerRady;
            } else if (YT.loaded) {
                onPlayerRady();
            } else {
                YT.ready(onPlayerRady);
            }

            function onPlayerRady() {
                console.log('Creating player');
                var player = new YT.Player(element.attr('id'), {
                    height: '390',
                    width: '640',
                    videoId: 'GE2BkLqMef4',
                    events: {
                        'onReady': onPlayerReady,
                            'onStateChange': onPlayerStateChange
                    }
                });
            }

            console.log(YT.loaded);
            // autoplay video
            function onPlayerReady(event) {
                console.log('autoplay');

                event.target.playVideo();
            }

            // when video ends
            function onPlayerStateChange(event) {
                if (event.data === 0) {
                    console.log('finsihed');

                    alert('done');
                }
            }

        }
    }
}]);

Demo