1. 程式人生 > >chrome 下視頻全屏播放後自定義控件無法使用的問題探究

chrome 下視頻全屏播放後自定義控件無法使用的問題探究

視頻 enc .cn java change 應該 自己的 視頻格式 code

chrome 63 升級到 64 後,我司旗下產品 講堂 出現了一個說大不大說小不小的 bug:自定義控件在全屏模式下失效了。

將代碼簡化如下:

<html>
<body>
  <video src="http://www.w3school.com.cn/i/movie.mp4" controls="controls" loop="loop"></video>
  <button style="z-index:2147483647;position:fixed;">
play/pause</button> </body> <script> var video = document.querySelector('video') var button = document.querySelector('button') button.onclick = e => { video.paused ? video.play() : video.pause() } </script> </html>

假設 button 為自定義控件,chrome 瀏覽器下,全屏後,該控件將無法使用(但依然可見)。其他瀏覽器表現不盡相同,firefox 下控件直接不顯示了,而 safari 下依然可用(個人認為 firefox 才是正確的姿勢,既然不能用,那就幹脆不顯示了,chrome 這樣算啥意思?)

將代碼進行了改進(只兼容 chrome 測試):

<html>
<style>
  .fullscreen {width:100%; height:100%;}
  .fullscreen video {width:100%; height:100%;}
</style>
<body>
  <div class="wrapper">
    <video src="http://www.w3school.com.cn/i/movie.mp4" controls="controls" loop=
"loop"></video> <button style="z-index:2147483647;position:fixed;left:0;top:100px;">play/pause</button> <button style="z-index:2147483647;position:fixed;left:100px;top:100px" id="fullscreen">fullscreen</button> </div> </body> <script> var video = document.querySelector('video') var button = document.querySelector('button') var fullscreenBtn = document.querySelector('#fullscreen') var wrapper = document.querySelector(".wrapper") button.onclick = e => { video.paused ? video.play() : video.pause() } fullscreenBtn.onclick = e => { wrapper.webkitRequestFullScreen() } document.addEventListener("webkitfullscreenchange", () => { wrapper.classList.add('fullscreen') }) </script> </html>

這樣 點擊自定義全屏控件 全屏後,就能使用自定義控件了。

這樣實現,需要同時滿足以下幾個條件:

  • 全屏操作需要用自定義控件調用 fullScreen API 觸發,而不是用默認的 video 中的控件
  • video 元素用一個 wrapper 元素包裹,自定義控件同時在這個 wrapper 元素內,點擊全屏的自定義控件,該 wrapper 元素調用 fullScreen API

而在實際開發中,由於用了 video.js,其實初始化的時候會自動在 wrapper 元素內生成 video 元素,另外會在該 wrapper 中加上 video.js 自身的一些控件(其實我們網站中沒有用到,只用到了 videojs 解析 m3u8 視頻格式的功能)。

代碼大概這樣子:

// 在 #sfLive 元素內生成 vedio 元素
const videoPlayer = videojs('sfLive', option, function onPlayerReady() {
  if (navigator.userAgent.indexOf('Firefox') != -1) { //火狐瀏覽器使用默認的控件
    $('video').attr('controls', true)
  }

  // 初始化成功後的回調
  // ...
})

而自定義控件,其實就是自己的一段 html 代碼,我們希望 videojs 有這樣一個 API,能在初始化的時候,wrapper 內生成自己的元素代碼的時候,將我們的自定義元素的 html 代碼也包裹進去。但是我沒有找到,或者找到的 API 看起來比較麻煩。

最終我采用了一個比較臟的方法,因為之前自定義控件元素其實已經生成了,只是位置不對 (參照需要同時滿足以下條件的第二條),那麽我就將他 remove 到該去的位置就好了,值得註意的是,這個 remove 的時機要把握正確(應該在 videojs 初始化元素成功後的回調裏),然後自定義控件的事件要處理好,這些事件必須在 remove 好後才能去監聽(不然會監聽 remove 前的元素了)

const videoPlayer = videojs('sfLive', option, function onPlayerReady() {
  if (navigator.userAgent.indexOf('Firefox') != -1) { //火狐瀏覽器使用默認的控件
    $('video').attr('controls',true)
  }
  
  // 將自定義控件移到 <video></video> 標簽中,解決全屏下無法點擊的問題
  try {
    // 將自定義控件位置移動
    $('#sfLive').append($('.live__playcontrol').remove())

    // 初始化自定義控件的一些監聽事件等
    playerController.init();
  } catch(err){}
})

chrome 下視頻全屏播放後自定義控件無法使用的問題探究