【问题标题】:YouTube API - iframe onStateChange eventsYouTube API - iframe onStateChange 事件
【发布时间】: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();}} 的方式放入一个事件处理程序 - 希望有人可以演示它是如何产生结果的。恐怕真的帮不上忙。

标签: javascript youtube youtube-api


【解决方案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);
         }
      })();
      

      【讨论】:

        猜你喜欢
        • 2015-11-07
        • 1970-01-01
        • 2015-10-13
        • 2013-06-09
        • 2014-09-22
        • 2013-06-09
        • 1970-01-01
        • 2012-04-17
        相关资源
        最近更新 更多