如何監聽頁面關閉或刷新動做

原文:如何監聽頁面關閉或刷新動做-fengxianqiphp

其實這篇文章也能夠叫如何監聽並上傳用戶觀看的視頻時長。最近有需求作到,監聽用戶播放視頻的動做並上報播放事件,須要上報的是用戶觀看視頻的時長。這裏就有幾種狀況了,一是用戶點擊播放,而後直到視頻播放完畢,觸發video.ended事件,此時上報用戶的觀看時長,這個比較好處理。第二種狀況是用戶點擊播放後離開或刷新頁面,在用戶離開前須要把事件上報,這裏主要會觸發window.onunload事件,看起來能夠作到,其實有坑。html

因爲公司採用的技術方案是.m3u8(hls),而這種格式目前PC瀏覽器只有Safari才支持,chrome、Firefox或移動端安卓其餘的大部分瀏覽器都不支持播放這種格式。所以,用原生video標籤的方案是不行了,得找一些插件或播放器。最終選擇了DPlayer這個播放器,一個比較不錯的開源播放器,簡單易用。 說回正事,上報用戶觀看視頻的時長。ios

重要更新

經評論區 @音客 指點,使用Navigator.sendBeacon()將會更好的支持上報事件,這是一個專門處理數據埋點的api,可是使用時請注意瀏覽器兼容性問題,目前(2018.06)移動端Android 5以上支持,ios須要11.3版本以上,具體請看CanIUse。 本篇使用new Image()方法能夠做爲sendBeacon()的不兼容時的降級處理方法,更多請參考:使用 navigator.sendBeacon() 上報數據ajax

目標

用戶觀看視頻結束時上報觀看時長。chrome

準備工做

const dp = new DPlayer({
        container: document.getElementById('dplayer'),
        screenshot: true,
        video: {
            url: 'xx.m3u8',
            pic: 'xx.jpg',
            type: 'customHls',
            customType: {
                'customHls': function (video, player) {
                    const hls = new Hls();
                    hls.loadSource(video.src);
                    hls.attachMedia(video);
                }
            }
        }
    });

    // 是否播放的標記
    var isPlay = false;
    dp.on('play', function () {
        console.log('player start');
        isPlay = true;
    });
複製代碼

第一種常規的狀況,用戶完整地看完了視頻。

dp.on('ended', function () {
      console.log('player ended');
      sendVideoPlayEvent(); //上報事件方法
      isPlay = false;
    });
複製代碼

第二種狀況,關閉瀏覽器或刷新頁面

用戶關閉頁面或刷新瀏覽器時會觸發onunload事件,用戶開始觀看視頻到離開頁面,這一段時間就是用戶觀看視頻的時長。api

window.onunload = function () {
      sendVideoPlayEvent();
      isPlay = false;
      console.log('onunload');
    };
複製代碼

坑點

經測試發現,sendVideoPlayEvent時,若是採用ajax,不管是post或get方式,將無效。這裏的緣由多是頁面關閉太快,ajax沒法執行。 查了不少解決方案,最後發現,須要經過巧妙的方法來發起這個事件。就是利用img標籤的src屬性,將img插入到body中時會發起一個請求來獲取資源,而服務端能夠對這個路由進行處理,最後發現這種方法是可行的,成功地在onunload中上報事件了。瀏覽器

function sendVideoPlayEvent() {
      if (isPlay) {
        var videoId = getQueryString('videoId');
        var duration = dp.video.currentTime; // 視頻播放時間能夠直接經過currentTime得到
        var img = new Image();
        img.style.display = 'none';
        img.src = `/api/video/play?duration=${duration}&videoId=${videoId}`; // 服務端處理接口
        document.body.appendChild(img);
      }
    }
    function getQueryString(name) {
        var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
        var r = window.location.search.substr(1).match(reg);
        if (r != null) return unescape(r[2]); return null;
    }
複製代碼

總結

  1. 後來想一想,script標籤的src應該也能夠實現,沒去驗證。
  2. 坑老是不少,多動腦筋。。。
  3. 思路有點侷限,應該還有其餘解決方案,歡迎建議。
相關文章
相關標籤/搜索