【问题标题】:Using Youtube's javascript API with jQuery在 jQuery 中使用 Youtube 的 javascript API
【发布时间】:2010-10-21 15:29:06
【问题描述】:

我目前正在尝试将 YouTube API 用作 jQuery 插件的一部分,但遇到了一些问题。

YT api 的工作方式是加载 Flash 播放器,当它准备好时,它会向名为 onYouTubePlayerReady(playerId) 的全局函数发送回调。然后,您可以将该 ID 与 getElementById(playerId) 结合使用,将 JavaScript 调用发送到 Flash 播放器(即 player.playVideo();)。

您可以使用player.addEventListener('onStateChange', 'playerState'); 将事件侦听器附加到播放器,这会将任何状态更改发送到另一个全局函数(在本例中为playerState)。

问题是我不确定如何将状态更改与特定玩家相关联。我的 jQuery 插件可以愉快地将多个视频附加到一个选择器并为每个视频附加事件,但是当状态实际发生变化时,我会忘记它发生在哪个播放器中。

我希望一些示例代码可以让事情变得更清楚一些。下面的代码应该可以在任何 html 文件中正常工作。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="application/text+html;utf-8"/>

  <title>Sandbox</title>

  <link type="text/css" href="http://jqueryui.com/latest/themes/base/ui.all.css" rel="stylesheet" />
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
    google.load("jquery", "1.3.2");
    google.load("jqueryui", "1.7.0");
</script>
<script type="text/javascript" src="http://swfobject.googlecode.com/svn/tags/rc3/swfobject/src/swfobject.js"></script>
<script type="text/javascript">
(function($) {
    $.fn.simplified = function() {
        return this.each(function(i) {
            var params = { allowScriptAccess: "always" };
            var atts = { id: "ytplayer"+i };
            $div = $('<div />').attr('id', "containerplayer"+i);
            swfobject.embedSWF("http://www.youtube.com/v/QTQfGd3G6dg&enablejsapi=1&playerapiid=ytplayer"+i, 
                               "containerplayer"+i, "425", "356", "8", null, null, params, atts);
            $(this).append($div);
        });
    }
})(jQuery);
function onYouTubePlayerReady(playerId) {
    var player = $('#'+playerId)[0];
    player.addEventListener('onStateChange', 'playerState');
}
function playerState(state) {
    console.log(state);
}

$(document).ready(function() {
    $('.secondary').simplified();
});
</script>
</head>
<body>
    <div id="container">
        <div class="secondary">

        </div>
        <div class="secondary">

        </div>
        <div class="secondary">

        </div>
        <div class="secondary">

        </div>

    </div>
</body>

</html>

您会看到 console.log() 输出有关状态变化的信息,但是,就像我说的,我不知道如何判断它与哪个玩家相关联。

有人对解决这个问题有什么想法吗?

编辑: 抱歉,我还应该提到我已经尝试将事件调用包装在闭包中。

function onYouTubePlayerReady(playerId) {
    var player = $('#'+playerId)[0];
    player.addEventListener('onStateChange', function(state) { 
    return playerState(state, playerId, player); } );
}

function playerState(state, playerId, player) {
    console.log(state);
    console.log(playerId);
}

在这种情况下,playerState 永远不会被调用。这更令人沮丧。

【问题讨论】:

    标签: javascript jquery api events youtube


    【解决方案1】:

    编辑:

    显然在player 对象上调用addEventListener 会导致脚本被用作传递给flash 对象的XML 属性中的字符串——这排除了闭包之类的情况,所以是时候使用老派了丑陋的黑客:

    function onYouTubePlayerReady(playerId) {
        var player = $('#'+playerId)[0];
    
        player.addEventListener('onStateChange', '(function(state) { return playerState(state, "' + playerId + '"); })' );
    }
    
    function playerState(state, playerId) {
        console.log(state);
        console.log(playerId);
    }
    

    测试和工作!

    【讨论】:

    • 这也是我的第一个想法,但它实际上在这里不起作用。 playerState 似乎从未被调用过。
    • 我已经测试了您发布的代码,并且从未调用过 onYouTubePlayerReady
    • 你确定你得到了所有的代码?我刚刚重新测试了它,当视频加载时,我得到了四个 5 输出到我的 console.log。这些视频真的会为您显示吗?
    • 啊,显然只有通过网络服务器访问它才有效。看起来 addEventListener 只接受一个字符串 - 我不知道为什么......
    • 好吧,我以为我快疯了。很高兴看到其他人对 YT 如何实现事件感到有些困惑。我想我可能不得不用这个回到绘图板上。我只是希望有人可能有一个天才。
    【解决方案2】:

    我正在使用 Jquery SWFobject 插件,SWFobject

    在视频末尾加上 &enablejsapi=1 很重要

    HTML:

    <div id="embedSWF"></div>
    

    jquery:

                 $('#embedSWF').flash({ 
                    swf: 'http://www.youtube.com/watch/v/siBoLc9vxac',
                    params: { allowScriptAccess: "always"},   
                    flashvars: {enablejsapi: '1', autoplay: '0', allowScriptAccess: "always", id: 'ytPlayer' },   
                    height: 450,   width: 385 });
    
    function onYouTubePlayerReady(playerId) {
                    $('#embedSWF').flash(function(){this.addEventListener("onStateChange", "onPlayerStateChange")});
                }
    function onPlayerStateChange(newState) {
                       alert(newState);
                     }
    

    onYouTubePlayerReady 必须在 $(document).ready(function() 之外才能被解雇

    【讨论】:

    • "onYouTubePlayerReady 必须在 $(document).ready(function() 之外才能被解雇" -- 你救了我的命
    • 一个小提示:onYouTubePlayerReady() 函数代码可以 $(document).ready,但它必须作用域到jQuery 之外的窗口/全局对象,因此需要将函数定义为:window.onYouTubePlayerReady(playerId) {}
    【解决方案3】:

    我遇到了同样的问题并尝试了接受的答案。这对我不起作用; playerState() 函数从未被调用过。然而,它让我走上了正确的道路。我最终做的是:

    // Within my mediaController "class"
    window["dynamicYouTubeEventHandler" + playerID] = function(state) { onYouTubePlayerStateChange(state, playerID); }
      embedElement.addEventListener("onStateChange", "dynamicYouTubeEventHandler" + playerID);
    // End mediaController class
    
    // Global YouTube event handler
    function onYouTubePlayerStateChange(state, playerID) {
      var mediaController = GetMediaControllerFromYouTubeEmbedID(playerID);
      mediaController.OnYouTubePlayerStateChange(state);
    }
    

    这很糟糕,但 YouTube JavaScript API 的当前状态也是如此。


    如果您使用任何类型的高级原型设计模式,这里还有一些有用/讨厌的代码。这基本上允许您从 YouTube 播放器 ID 中检索“类”实例:

    // Within my mediaController "class"
    // The containerJQElement is the jQuery wrapped parent element of the player ID
    // Its ID is the same as the player ID minus "YouTubeEmbed".
    var _self = this;
    containerJQElement.data('mediaController', _self);
    // End mediaController class
    
    // Global YouTube specific functions
    function GetMediaControllerFromYouTubeEmbedID(embedID) {      
      var containerID = embedID.replace('YouTubeEmbed', '');
      var containerJQObject = $("#" + containerID);
      return containerJQObject.data('mediaController');      
    }
    
    function onYouTubePlayerReady(playerId) {
      var mediaController = GetMediaControllerFromYouTubeEmbedID(playerId);
      mediaController.OnYouTubeAPIReady();
    }
    

    【讨论】:

    • 这对我来说不是很清楚。我在哪里可以获得 mediaController “类”?
    • @Volomike 它只是一个自定义的 JavaScript 对象,用于帮助控制 YouTube 元素。
    【解决方案4】:

    这是一篇不错的文章,介绍了如何创建一个类来包装单个玩家,包括使用与上一个答案中提到的方法类似的方法将事件分派到单个对象。

    http://blog.jcoglan.com/2008/05/22/dispatching-youtube-api-events-to-individual-javascript-objects/

    【讨论】:

      【解决方案5】:

      这样的事情怎么样:

      var closureFaker = function (func, scope) {
          var functionName = 'closureFake_' + (((1+Math.random())*0x10000000)|0).toString(16);
          window[functionName] = function () {
              func.apply(scope || window, arguments);
          };
          console.log('created function:', functionName, window[functionName]);
          return functionName;
      };
      
      ytplayer.addEventListener("onStateChange", closureFaker(function () {
          //place your logic here
          console.log('state change', arguments)
      }));
      

      【讨论】:

        猜你喜欢
        • 2016-03-20
        • 2020-10-20
        • 2014-01-26
        • 2011-05-04
        • 1970-01-01
        • 2011-01-29
        • 2013-08-10
        • 2012-09-08
        • 1970-01-01
        相关资源
        最近更新 更多