YouTube API - iframe onStateChange 事件
Posted
技术标签:
【中文标题】YouTube API - iframe onStateChange 事件【英文标题】:YouTube API - iframe onStateChange events 【发布时间】:2014-08-28 13:52:10 【问题描述】:我正在使用 iframe YouTube API,我想跟踪事件,例如,当用户开始和停止视频时,将数据发送到谷歌分析。
<iframe src="https://www.youtube.com/embed/DjB1OvEYMhY"></iframe>
我查看了https://developers.google.com/youtube/iframe_api_reference?csw=1 并没有找到如何做到这一点的示例。该示例创建 iframe 并定义了 onReady 和 onStateChange。如果页面上只有 iframe,我该怎么做?
【问题讨论】:
您应该能够按照function getPlayerState() if (ytplayer) return ytplayer. getPlayerState();
的方式放入一个事件处理程序 - 希望有人可以演示它是如何产生结果的。恐怕真的帮不上忙。
【参考方案1】:
此示例使用 onPlayerStateChange
及其不同的 states 监听用户所做的每个播放/暂停操作,并打印(记录)它们。
但是,您需要创建自己的 record
函数才能对这些数据执行任何操作。
您还需要 iframe 上的 ID(在本例中为 #player)并在其 URL 的末尾添加 ?enablejsapi=1。当然,请确保包含Youtube iframe API。
注意
在您的代码之后声明 API 很重要,因为它会在准备好时调用 onYouTubeIframeAPIReady
。
<!DOCTYPE html>
<html>
<body>
<iframe id="player" src="https://www.youtube.com/embed/DjB1OvEYMhY?enablejsapi=1"></iframe>
<h5>Record of user actions:</h5>
<script>
var player;
function onYouTubeIframeAPIReady()
player = new YT.Player( 'player',
events: 'onStateChange': onPlayerStateChange
);
function onPlayerStateChange(event)
switch(event.data)
case 0:
record('video ended');
break;
case 1:
record('video playing from '+player.getCurrentTime());
break;
case 2:
record('video paused at '+player.getCurrentTime());
function record(str)
var p = document.createElement("p");
p.appendChild(document.createTextNode(str));
document.body.appendChild(p);
</script>
<script src="https://www.youtube.com/iframe_api"></script>
</body>
</html>
JS Fiddle Demo
【讨论】:
【参考方案2】:这是一个不使用 Youtubes iframe API 脚本的版本。唯一的缺点是 iframe API 可能会改变。
<iframe id="player" src="https://www.youtube.com/embed/dQw4w9WgXcQ?enablejsapi=1"></iframe>
var addYoutubeEventListener = (function()
var callbacks = [];
var iframeId = 0;
return function (iframe, callback)
// init message listener that will receive messages from youtube iframes
if(iframeId === 0)
window.addEventListener("message", function (e)
if(e.origin !== "https://www.youtube.com" || e.data === undefined) return;
try
var data = JSON.parse(e.data);
if(data.event !== 'onStateChange') return;
var callback = callbacks[data.id];
callback(data);
catch(e)
);
// store callback
iframeId++;
callbacks[iframeId] = callback;
var currentFrameId = iframeId;
// sendMessage to frame to start receiving messages
iframe.addEventListener("load", function ()
var message = JSON.stringify(
event: 'listening',
id: currentFrameId,
channel: 'widget'
);
iframe.contentWindow.postMessage(message, 'https://www.youtube.com');
message = JSON.stringify(
event: "command",
func: "addEventListener",
args: ["onStateChange"],
id: currentFrameId,
channel: "widget"
);
iframe.contentWindow.postMessage(message, 'https://www.youtube.com');
);
)();
addYoutubeEventListener(document.getElementById("player"), function(e)
switch(e.info)
case 1:
// playing
break;
case 0:
// ended
break;
);
【讨论】:
【参考方案3】:有时事件加载不足以确保 iframe 内的文档准备就绪。如果 iframe 位于不同的域中,则无法订阅以查看它何时准备就绪。
一种可能的解决方法是记录从 iframe 接收到事件的时间,如果在订阅后未收到任何事件,请重试:
var addYoutubeEventListener = (function()
var callbacks = [];
var iframeId = 0;
var subscribed = [];
return function (iframe, callback)
// init message listener that will receive messages from youtube iframes
if(iframeId === 0)
window.addEventListener("message", function (e)
if(e.origin !== "https://www.youtube.com" || e.data === undefined) return;
try
var data = JSON.parse(e.data);
subscribed[data.id] = true;
if(data.event !== 'onStateChange') return;
var callback = callbacks[data.id];
callback(data);
catch(e)
, true);
// store callback
iframeId++;
callbacks[iframeId] = callback;
subscribed[iframeId] = false;
var currentFrameId = iframeId;
//console.log("adding event listener to iframe id " + iframeId);
// sendMessage to frame to start receiving messages
iframe.addEventListener("load", function ()
var tries = 0;
var checkSubscribed = function()
if (subscribed[currentFrameId])
//console.log("subscribed succesfully " + currentFrameId)
else
tries++;
//console.log("Try again " + currentFrameId + " (" + tries + ")");
if (tries < 100)
doSubscribe();
else
console.log("Unable to subscribe" + currentFrameId );
var doSubscribe = function()
var message = JSON.stringify(
event: 'listening',
id: currentFrameId,
channel: 'widget'
);
iframe.contentWindow.postMessage(message, 'https://www.youtube.com');
message = JSON.stringify(
event: "command",
func: "addEventListener",
args: ["onStateChange"],
id: currentFrameId,
channel: "widget"
);
iframe.contentWindow.postMessage(message, 'https://www.youtube.com');
setTimeout(checkSubscribed, 100);
;
doSubscribe();
, true);
)();
【讨论】:
以上是关于YouTube API - iframe onStateChange 事件的主要内容,如果未能解决你的问题,请参考以下文章
动态创建的 iFrame 上的 YouTube iFrame API
如何启动和停止使用youtube iframe API创建的YouTube视频?
无法通过 api 调用 pauseVideo 访问 youtube 嵌入式 iframe