【问题标题】:Listening for Youtube Event in JavaScript or jQuery用 JavaScript 或 jQuery 监听 Youtube 事件
【发布时间】:2011-12-20 18:27:15
【问题描述】:

我有一个滑块,其中包括 4 个通过 iframe 嵌入代码嵌入的 youtube 视频

http://www.youtube.com/embed/'.$i.'?enablejsapi=1

我正在尝试使四个视频中的任何一个的 onStateChange 事件调用我称为 stopCycle() 的函数,该函数将在视频开始播放时停止滑块。 iframe 没有 id。我不确定如何正确捕获此事件,并且可以就我做错的事情提出任何建议。

<script charset="utf-8" type="text/javascript" src="http://www.youtube.com/player_api"></script>

var playerObj = document.getElementById("tab2"); // the container for 1 of the 4 iframes

playerObj.addEventListener("onStateChange", "stopCycle");

function stopCycle(event) {
    alert('Stopped!');
}

【问题讨论】:

    标签: javascript jquery events youtube youtube-api


    【解决方案1】:

    YouTube Frame API确实支持现有框架。为了改进使用,我创建了一些辅助函数。看看下面的代码+cmets和demo:http://jsfiddle.net/YzvXa/197

    要将函数绑定到现有框架,您必须将 ID 引用传递给框架。在您的情况下,框架包含在带有id="tab2" 的容器中。我已经定义了一个自定义函数以便于实现:

    function getFrameID(id){
        var elem = document.getElementById(id);
        if (elem) {
            if(/^iframe$/i.test(elem.tagName)) return id; //Frame, OK
            // else: Look for frame
            var elems = elem.getElementsByTagName("iframe");
            if (!elems.length) return null; //No iframe found, FAILURE
            for (var i=0; i<elems.length; i++) {
               if (/^https?:\/\/(?:www\.)?youtube(?:-nocookie)?\.com(\/|$)/i.test(elems[i].src)) break;
            }
            elem = elems[i]; //The only, or the best iFrame
            if (elem.id) return elem.id; //Existing ID, return it
            // else: Create a new ID
            do { //Keep postfixing `-frame` until the ID is unique
                id += "-frame";
            } while (document.getElementById(id));
            elem.id = id;
            return id;
        }
        // If no element, return null.
        return null;
    }
    
    // Define YT_ready function.
    var YT_ready = (function() {
        var onReady_funcs = [], api_isReady = false;
        /* @param func function     Function to execute on ready
         * @param func Boolean      If true, all qeued functions are executed
         * @param b_before Boolean  If true, the func will added to the first
                                     position in the queue*/
        return function(func, b_before) {
            if (func === true) {
                api_isReady = true;
                while (onReady_funcs.length) {
                    // Removes the first func from the array, and execute func
                    onReady_funcs.shift()();
                }
            } else if (typeof func == "function") {
                if (api_isReady) func();
                else onReady_funcs[b_before?"unshift":"push"](func); 
            }
        }
    })();
    // This function will be called when the API is fully loaded
    function onYouTubePlayerAPIReady() {YT_ready(true)}
    
    // Load YouTube Frame API
    (function() { // Closure, to not leak to the scope
      var s = document.createElement("script");
      s.src = (location.protocol == 'https:' ? 'https' : 'http') + "://www.youtube.com/player_api";
      var before = document.getElementsByTagName("script")[0];
      before.parentNode.insertBefore(s, before);
    })();
    

    // 之前定义了核心功能。展望实施:

    var player; //Define a player object, to enable later function calls, without
                // having to create a new class instance again.
    
    // Add function to execute when the API is ready
    YT_ready(function(){
        var frameID = getFrameID("tabs2");
        if (frameID) { //If the frame exists
            player = new YT.Player(frameID, {
                events: {
                    "onStateChange": stopCycle
                }
            });
        }
    });
    
    // Example: function stopCycle, bound to onStateChange
    function stopCycle(event) {
        alert("onStateChange has fired!\nNew state:" + event.data);
    }
    

    如果您想稍后调用其他函数,例如将视频静音,使用:

    player.mute();
    
    • 如果您只需要调用简单的单向函数,则无需使用此代码。相反,请使用 this answer 中定义的函数 callPlayer
    • 如果您想同时为多帧实现此功能,请查看this answer还包括getFrameIDYT_ready的详细解释

    【讨论】:

    • 您能举例说明在我的场景中使用该功能需要做些什么吗?
    • @DaveKiss 如果 IFrame 是使用 YouTube Frame API 动态生成的,您可以查看第二个链接。否则,您必须稍等片刻,因为尚未实现双向事件侦听器。我正在努力。
    • 你能在这个功能实现后更新这个问题吗?
    • @RobW 我在原始问题上提供了一个示例,因此您可以看到我正在尝试做什么 - 基本上是在单击自定义缩略图时开始播放视频。这是我为未来访问者提出的问题的链接 - stackoverflow.com/questions/8948403/…
    • @absynthe mindwebsmith 使用if-statement,例如:if (event.data == -1) return;
    【解决方案2】:

    您可以使用tubeplayer 插件,它带有很多要监听的事件。

    【讨论】:

    • 我的 iframe 无法动态生成,它们是通过 php 创建的。
    【解决方案3】:

    从昨天开始,这不再起作用了。 onStateChange 不会被触发。 Jeffrey 发布了一个快速修复,但我无法更新上述答案

    关于这个问题的更多信息https://code.google.com/p/gdata-issues/issues/detail?id=4706

    得到它的工作 :-) 修复

    添加如下函数

    function onReady() {
        player.addEventListener('onStateChange', function(e) {
            console.log('State is:', e.data);
        });
    }
    

    在 "onStateChange":stopCycle 之前添加 "onReady":onReady,

    【讨论】:

      【解决方案4】:

      我的聊天中有此功能,可让用户从 youtube 发布视频。 vid 的 url 作为现有 iframe 的来源附加,带有 id。

      我注意到 - 尽管添加了 ?enablejsapi=1 - 该脚本仅适用于页面加载时现有的 iframe。

      在为 iframe 设置新源后,如果希望此脚本绑定,该怎么办?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-18
        • 2012-01-22
        • 1970-01-01
        • 1970-01-01
        • 2016-10-15
        • 2020-06-21
        • 1970-01-01
        相关资源
        最近更新 更多