YouTube iframe API:如何控制已经在HTML中的iframe播放器? [英] YouTube iframe API: how do I control a iframe player that's already in the HTML?

查看:282
本文介绍了YouTube iframe API:如何控制已经在HTML中的iframe播放器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望能够控制基于iframe的YouTube播放器。这些播放器已经在HTML中,但我想通过JavaScript API控制它们。

I want to be able to control iframe based YouTube players. This players will be already in the HTML, but I want to control them via the JavaScript API.

我一直在阅读 iframe API的文档,说明如何使用API​​向网页添加新视频,然后使用YouTube播放器功能控制它:

I've been reading the documentation for the iframe API which explain how to add a new video to the page with the API, and then control it with the YouTube player functions:

var player;
function onYouTubePlayerAPIReady() {
    player = new YT.Player('container', {
        height: '390',
        width: '640',
        videoId: 'u1zgFlCw8Aw',
        events: {
            'onReady': onPlayerReady,
            'onStateChange': onPlayerStateChange
        }
    });
}

该代码创建一个新的玩家对象并将其分配给玩家,然后将其插入#container div中。然后我可以操作'播放器'并在其上调用 playVideo() pauseVideo()等。

That code creates a new player object and assigns it to 'player', then inserts it inside the #container div. Then I can operate on 'player' and call playVideo(), pauseVideo(), etc. on it.

但我希望能够对页面上已经存在的iframe播放器进行操作。

我可以使用旧的embed方法很容易地做到这一点,例如:

I could do this very easily with the old embed method, with something like:

player = getElementById('whateverID');
player.playVideo();

但这不适用于新的iframe。如何在页面上分配iframe对象,然后在其上使用API​​函数?

But this doesn't work with the new iframes. How can I assign a iframe object already on the page and then use the API functions on it?

推荐答案

小提琴链接:源代码 - 预览 - 小版本

更新:这个小功能只会在单个方向上执行代码。如果您需要完全支持(例如事件监听器/ getter),请查看 at 在jQuery中收听Youtube事件

Fiddle Links: Source code - Preview - Small version
Update: This small function will only execute code in a single direction. If you want full support (eg event listeners / getters), have a look at Listening for Youtube Event in jQuery

由于深度代码分析,我创建了一个功能:函数callPlayer 请求对任何带框的YouTube视频进行函数调用。请参阅 YouTube Api参考以获取可能的函数调用的完整列表。阅读源代码中的注释以获得解释。

As a result of a deep code analysis, I've created a function: function callPlayer requests a function call on any framed YouTube video. See the YouTube Api reference to get a full list of possible function calls. Read the comments at the source code for an explanation.

2012年5月17日,代码大小加倍,以便处理播放器的就绪状态。如果您需要一个不处理播放器就绪状态的紧凑功能,请参阅 http://jsfiddle.net/8R5y6/

On 17 may 2012, the code size was doubled in order to take care of the player's ready state. If you need a compact function which does not deal with the player's ready state, see http://jsfiddle.net/8R5y6/.

/**
 * @author       Rob W <gwnRob@gmail.com>
 * @website      https://stackoverflow.com/a/7513356/938089
 * @version      20131010
 * @description  Executes function on a framed YouTube video (see website link)
 *               For a full list of possible functions, see:
 *               https://developers.google.com/youtube/js_api_reference
 * @param String frame_id The id of (the div containing) the frame
 * @param String func     Desired function to call, eg. "playVideo"
 *        (Function)      Function to call when the player is ready.
 * @param Array  args     (optional) List of arguments to pass to function func*/
function callPlayer(frame_id, func, args) {
    if (window.jQuery && frame_id instanceof jQuery) frame_id = frame_id.get(0).id;
    var iframe = document.getElementById(frame_id);
    if (iframe && iframe.tagName.toUpperCase() != 'IFRAME') {
        iframe = iframe.getElementsByTagName('iframe')[0];
    }

    // When the player is not ready yet, add the event to a queue
    // Each frame_id is associated with an own queue.
    // Each queue has three possible states:
    //  undefined = uninitialised / array = queue / 0 = ready
    if (!callPlayer.queue) callPlayer.queue = {};
    var queue = callPlayer.queue[frame_id],
        domReady = document.readyState == 'complete';

    if (domReady && !iframe) {
        // DOM is ready and iframe does not exist. Log a message
        window.console && console.log('callPlayer: Frame not found; id=' + frame_id);
        if (queue) clearInterval(queue.poller);
    } else if (func === 'listening') {
        // Sending the "listener" message to the frame, to request status updates
        if (iframe && iframe.contentWindow) {
            func = '{"event":"listening","id":' + JSON.stringify(''+frame_id) + '}';
            iframe.contentWindow.postMessage(func, '*');
        }
    } else if (!domReady ||
               iframe && (!iframe.contentWindow || queue && !queue.ready) ||
               (!queue || !queue.ready) && typeof func === 'function') {
        if (!queue) queue = callPlayer.queue[frame_id] = [];
        queue.push([func, args]);
        if (!('poller' in queue)) {
            // keep polling until the document and frame is ready
            queue.poller = setInterval(function() {
                callPlayer(frame_id, 'listening');
            }, 250);
            // Add a global "message" event listener, to catch status updates:
            messageEvent(1, function runOnceReady(e) {
                if (!iframe) {
                    iframe = document.getElementById(frame_id);
                    if (!iframe) return;
                    if (iframe.tagName.toUpperCase() != 'IFRAME') {
                        iframe = iframe.getElementsByTagName('iframe')[0];
                        if (!iframe) return;
                    }
                }
                if (e.source === iframe.contentWindow) {
                    // Assume that the player is ready if we receive a
                    // message from the iframe
                    clearInterval(queue.poller);
                    queue.ready = true;
                    messageEvent(0, runOnceReady);
                    // .. and release the queue:
                    while (tmp = queue.shift()) {
                        callPlayer(frame_id, tmp[0], tmp[1]);
                    }
                }
            }, false);
        }
    } else if (iframe && iframe.contentWindow) {
        // When a function is supplied, just call it (like "onYouTubePlayerReady")
        if (func.call) return func();
        // Frame exists, send message
        iframe.contentWindow.postMessage(JSON.stringify({
            "event": "command",
            "func": func,
            "args": args || [],
            "id": frame_id
        }), "*");
    }
    /* IE8 does not support addEventListener... */
    function messageEvent(add, listener) {
        var w3 = add ? window.addEventListener : window.removeEventListener;
        w3 ?
            w3('message', listener, !1)
        :
            (add ? window.attachEvent : window.detachEvent)('onmessage', listener);
    }
}

用法:

callPlayer("whateverID", function() {
    // This function runs once the player is ready ("onYouTubePlayerReady")
    callPlayer("whateverID", "playVideo");
});
// When the player is not ready yet, the function will be queued.
// When the iframe cannot be found, a message is logged in the console.
callPlayer("whateverID", "playVideo");



可能的问题(&答案):



Q :它不起作用!

A :不起作用不是一个明确的描述。你收到任何错误信息吗?请显示相关代码。

Possible questions (& answers):

Q: It doesn't work!
A: "Doesn't work" is not a clear description. Do you get any error messages? Please show the relevant code.

:我使用< iframe src =http嵌入了YouTube视频://www.youtube.com/embed/As2rZGPGKDY/> 但该功能不执行任何功能!

A :你必须在网址末尾添加?enablejsapi = 1 / embed / vid_id?enablejsapi = 1

Q: I have embedded a YouTube video using <iframe src="http://www.youtube.com/embed/As2rZGPGKDY" />but the function doesn't execute any function!
A: You have to add ?enablejsapi=1 at the end of your URL: /embed/vid_id?enablejsapi=1.

:我收到错误消息指定了无效或非法的字符串。为什么?

A :API在本地主机上无法正常运行( file:// )。在线托管您的(测试)页面,或使用 JSFiddle 。示例:请参阅此答案顶部的链接。

Q: I get error message "An invalid or illegal string was specified". Why?
A: The API doesn't function properly at a local host (file://). Host your (test) page online, or use JSFiddle. Examples: See the links at the top of this answer.

:您是怎么知道的?

A :我花了一些时间来手动解释API的来源。我总结说我必须使用 postMessage 方法。要知道要传递哪些参数,我创建了一个拦截邮件的Chrome扩展程序。扩展程序的源代码可以这里下载。

Q: How did you know this?
A: I have spent some time to manually interpret the API's source. I concluded that I had to use the postMessage method. To know which arguments to pass, I created a Chrome extension which intercepts messages. The source code for the extension can be downloaded here.

:支持哪些浏览器?

A :支持 JSON 的postMessage

Q: What browsers are supported?
A: Every browser which supports JSON and postMessage.


  • IE 8 +

  • Firefox 3.6+(实际上是3.5,但 document.readyState 在3.6)中实现。

  • Opera 10.50 +

  • Safari 4 +

  • Chrome 3 +

  • IE 8+
  • Firefox 3.6+ (actually 3.5, but document.readyState was implemented in 3.6)
  • Opera 10.50+
  • Safari 4+
  • Chrome 3+

相关答案/实施:使用jQuery淡化框架视频

完整的API支持:在jQuery中监听Youtube事件

官方API: https://developers.google.com/youtube/iframe_api_reference

Related answer / implementation: Fade-in a framed video using jQuery
Full API support: Listening for Youtube Event in jQuery
Official API: https://developers.google.com/youtube/iframe_api_reference


  • 2012年5月17日

    已实施 onYouTubePlayerReady callPlayer('frame_id',function(){...})

    函数在t时自动排队他还没有准备好。

  • 2012年7月24日

    在支持的浏览器中更新并成功测试(展望未来)。

  • 10十月2013
    当函数作为参数传递时, callPlayer 强制检查就绪状态。这是必需的,因为在文档准备好后插入iframe后立即调用 callPlayer 时,它无法确定iframe是否已完全就绪。在Internet Explorer和Firefox中,此方案导致过早调用 postMessage ,这被忽略。

  • 2013年12月12日,推荐在网址中添加& origin = *

  • 2014年3月2日,撤消建议删除& ; origin = * 到URL。

  • 17 may 2012
    Implemented onYouTubePlayerReady: callPlayer('frame_id', function() { ... }).
    Functions are automatically queued when the player is not ready yet.
  • 24 july 2012
    Updated and successully tested in the supported browsers (look ahead).
  • 10 october 2013 When a function is passed as an argument, callPlayer forces a check of readiness. This is needed, because when callPlayer is called right after the insertion of the iframe while the document is ready, it can't know for sure that the iframe is fully ready. In Internet Explorer and Firefox, this scenario resulted in a too early invocation of postMessage, which was ignored.
  • 12 Dec 2013, recommended to add &origin=* in the URL.
  • 2 Mar 2014, retracted recommendation to remove &origin=* to the URL.

这篇关于YouTube iframe API:如何控制已经在HTML中的iframe播放器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆