Youtube iframe API无法按预期工作

时间:2015-02-20 16:14:24

标签: javascript youtube youtube-api

在我的一个模态中,我想显示一个YouTube视频。哪一个(哪个ID)取决于用于打开模型的按钮。

<button class='yt-play' data-yt='xxxxxx'>Play video</button>

在我的javascript文件中,我使用YT player-api生成iframe;我跟着Getting started on google developers

所以在模态中我添加了一个<div id='player'></div>,这是我包含的javascript:

var tag = document.createElement('script');
    tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;

function onYouTubeIframeAPIReady() {
  player = new YT.Player('player', {
    videoId: '5ulO97zuVF0', //- just a temporary id
  });
}

// on document ready do some jQuery things, 
// like adding an event handler to the button. 
$(document).ready(function (){

   $('.yt-play').click(function(ev){
        ev.preventDefault();
        var videoid = $(this).data('yt');

        player.loadVideoById(videoid);
        $('#yt-player').modal('show');
        player.playVideo();

    });

});

yt-play上的点击处理程序应该按照所述here in the documentation的方式通过player.loadVideoById()加载视频。

但不知怎的,我收到了一个javascript错误:TypeError: player.loadVideoById is not a function

如果我将玩家对象转储到控制台中,我会得到一个漂亮的玩家对象;其中包含loadVideoById函数。至少它看起来像:

console screenshot

未加载新视频的原因是什么?

5 个答案:

答案 0 :(得分:1)

可能是因为&#34; loadVideoById&#34;还没有。

您必须使用事件对象构建YT.Player对象,并包含&#34; onReady&#34;事件回调。

然后在你的&#34; onReady&#34;绑定按钮点击事件的回调函数。

function onPlayerReady() {
    $('.yt-play').click(function(ev){
        ev.preventDefault();
        var videoid = $(this).data('yt');

        // player.loadVideoByID is now available as a function
        player.loadVideoById(videoid);

        $('#yt-player').modal('show');
        player.playVideo();
    });
}
player = new YT.Player('player', {
    videoId: '5ulO97zuVF0', //- just a temporary id,
    events:{
        “onReady”: onPlayerReady   
    }
});

请参阅文档中的事件部分了解更多信息:

https://developers.google.com/youtube/iframe_api_reference#Events

答案 1 :(得分:0)

  1. 在html文档中添加div元素
  2. onYouTubeIframeAPIReady函数中的全局对象的初始YT
  3. 在您的函数中调用YT对象

答案 2 :(得分:0)

代码:

<script>
    // load API
    var tag = document.createElement('script');
    tag.src = "https://www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

    // define player
    var player;
    function onYouTubeIframeAPIReady() {
        player = new YT.Player('player', {
            height: '360',
            width: '640'
        });
    }

    $(function () {

       // load video and add event listeners
       function loadVideo(id, start, end) {
          // check if player is defined
          if ((typeof player !== "undefined")) {
            // listener for player state change
            player.addEventListener('onStateChange', function (event) {
                if (event.data == YT.PlayerState.ENDED) {
                    // do something
                }
            });
            // listener if player is ready (including methods, like loadVideoById
            player.addEventListener('onReady', function(event){
                event.target.loadVideoById({
                    videoId: id,
                    startSeconds: start,
                    endSeconds: end
                });
                // pause player (my specific needs)
                event.target.pauseVideo();
            });
        }
        // if player is not defined, wait and try again
        else {
            setTimeout(loadVideo, 100, id, start, end);
        }
      }

      // somewhere in the code
      loadVideo('xxxxxxxx', 0, 3);
      player.playVideo();
   });
</script>

答案 3 :(得分:0)

其他答案无法澄清问题。

YouTube api确实令人困惑!这是因为YT.Player构造函数将dom引用返回到youtube播放器的iframe,而不是YT播放器对象。

为了获得对YT播放器的引用,我们需要监听onReady事件。

var ytPlayer;
var videoIframe = new YT.Player('player', {
                        videoId: 'xxxxxxx',  // youtube video id
                        playerVars: {
                                'autoplay': 0,
                                'rel': 0,
                                'showinfo': 0
                        },
                        events: {
                           'onStateChange': onPlayerStateChange,
                           'onReady': function (ev) {
                                ytPlayer = ev.target;
                            }
                        }
});

答案 4 :(得分:0)

聚会只迟到了 6 年,我有解决方案。

问题是 YouTube API 不像 DOM shuffling Foundation 在打开模态时那样。

实现此目的的唯一方法是在打开模式后创建 YouTube 播放器:

function play_video(ytid) {
    
    modal = new Foundation.Reveal($('#yt_modal'),{});
    modal.open();

    ytplayer = new YT.Player('ytplayer', {
        videoId: ytid,
        height: '390',
        width: '640',
        playerVars: {
            'playsinline': 1
        },
        events: {
            'onReady': whatever()
        }
    });
}

假设

<div id="ytplayer"></div>

在您的 Foundation 模态内。

哦,您每次都需要删除 iframe,否则 YouTube API 只会查找旧的 iframe(这不是它所期望的位置,因为模式已关闭且 DOM 已更改):

$(document).on('closed.zf.reveal', function(e) {
        switch($(e.target).prop('id')) {
            case 'yt_modal':
                ytplayer.destroy();
                break;
        }
    });

关于@Tosh 关于返回 iframe 引用的 API 的回答,就我可以通过将其与 onReady(ev.target) 返回的内容进行比较来确定,播放器不是真实的 - 它们看起来相同(所以不要不要像我一样走那条死胡同!)