我希望能够控制基于iframe的YouTube播放器。该播放器已经存在于HTML中,但是我想通过JavaScript API对其进行控制。
我一直在阅读iframeAPI的文档,其中解释了如何使用API向页面添加新视频,然后使用YouTube播放器功能对其进行控制:
var player; function onYouTubePlayerAPIReady() { player = new YT.Player('container', { height: '390', width: '640', videoId: 'u1zgFlCw8Aw', events: { 'onReady': onPlayerReady, 'onStateChange': onPlayerStateChange } }); }
该代码创建了一个新的播放器对象,并将其分配给“player”,然后将其插入#containerdiv中。然后,我可以在“播放器”和呼叫操作playVideo(),pauseVideo()就可以了,等等。
playVideo()
pauseVideo()
但我希望能够在页面上已经存在的iframe播放器上进行操作。
使用旧的embed方法,我可以很容易地做到这一点,例如:
player = getElementById('whateverID'); player.playVideo();
但这不适用于新的iframe。如何在页面上分配iframe对象,然后在其上使用API函数?
jsfiddle链接: 源代码 - 预览 - 小版本 更新:此小功能将仅在单个方向上执行代码。
经过深入的代码分析,我创建了一个函数:functioncallPlayer在任何带框架的YouTube视频上请求一个函数调用。
functioncallPlayer
代码大小增加了一倍,以照顾玩家的就绪状态。如果您需要一个不处理播放器就绪状态的紧凑功能,请参见http://jsfiddle.net/8R5y6/。
/** * @author Rob W <gwnRob@gmail.com> * @website https://stackoverflow.com/a/7513356/938089 * @version 20190409 * @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 / .ready=true = 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 ((!queue || !queue.ready) && ( !domReady || iframe && !iframe.contentWindow || 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");
问 :这不起作用! 答 :“不起作用”的描述不明确。您收到任何错误消息吗?请显示相关代码。
问 :playVideo不播放视频。 答 :播放需要用户互动以及allow="autoplay"iframe上的存在。
playVideo
allow="autoplay"
问 :我已经使用嵌入了YouTube视频,<iframesrc="http://www.youtube.com/embed/As2rZGPGKDY" />但是该功能没有执行任何功能! 答 :您必须?enablejsapi=1在URL末尾添加/embed/vid_id?enablejsapi=1。
<iframesrc="http://www.youtube.com/embed/As2rZGPGKDY" />
?enablejsapi=1
/embed/vid_id?enablejsapi=1
问 :我收到错误消息“指定了无效或非法的字符串”。为什么? 答 :API在本地主机(file://)上无法正常运行。在线托管您的(测试)页面,或使用JSFiddle。示例:请参见此答案顶部的链接。
file://
问 :您怎么知道的? 答 :我花了一些时间来手动解释API的来源。我得出的结论是我必须使用该postMessage方法。为了知道要传递哪些参数,我创建了一个Chrome扩展程序来拦截消息。扩展的源代码可以在这里下载。
postMessage
问 :支持哪些浏览器? 答 :每个支持JSON和的浏览器postMessage。
document.readyState
于2012年5月17日 实施onYouTubePlayerReady:callPlayer('frame_id', function() { ... })。 播放器尚未准备就绪时,功能会自动排队。
onYouTubePlayerReady
callPlayer('frame_id', function() { ... })
2012年7月24日, 更新并在受支持的浏览器中进行了成功测试(请注意)。
2013年10月10日当函数作为参数传递时,callPlayer强制检查准备情况。这是必需的,因为在callPlayer文档准备就绪后,在插入iframe之后立即调用时,无法确定iframe是否已完全准备就绪。在Internet Explorer和Firefox中,这种情况导致的调用太早postMessage,被忽略了。
callPlayer
&origin=*