chrome 下视频全屏播放后自定义控件无法使用的问题探究
Posted zichi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了chrome 下视频全屏播放后自定义控件无法使用的问题探究相关的知识,希望对你有一定的参考价值。
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 下视频全屏播放后自定义控件无法使用的问题探究的主要内容,如果未能解决你的问题,请参考以下文章
带有自定义控件的视频无法在 iOS 上播放(Safari 和 Chrome)