代码之家  ›  专栏  ›  技术社区  ›  Steerpike

在jquery中使用youtube的javascript API

  •  20
  • Steerpike  · 技术社区  · 17 年前

    我目前正试图将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);
    }
    

    在这种情况下 玩家状态 永远不会接到电话。这是非常令人沮丧的。

    5 回复  |  直到 15 年前
        1
  •  23
  •   Greg    17 年前

    编辑:

    显然是打电话来的 addEventListener 上 player 对象导致脚本在传递给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);
    }
    

    测试和工作!

        2
  •  6
  •   nbchip    17 年前

    我使用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()之外才能激发

        3
  •  2
  •   JoshNaro    16 年前

    我也遇到了同样的问题,尝试了公认的答案。这对我不起作用;从未调用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();
    }
    
        4
  •  1
  •   Paul Horsfall    17 年前

    这是一篇很好的文章,通过创建一个类来包装一个单独的播放器,包括使用与前面答案中提到的类似的方法将事件分派到单个对象。

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

        5
  •  1
  •   Leon Fedotov    15 年前

    像这样的怎么样:

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