这是我参与更文挑战的第10天,活动详情查看: 更文挑战
前言
虽然说这篇文章是为了实现播放器(video)全屏以及解决全屏遇到的问题,但是如果你是希望实现其他元素全屏,下面的全屏代码和一些问题的解决方案也是适用的,可以参考下。
播放器全屏代码
播放器进入全屏主要使用到了 requestFullscreen
(进入全屏) 和 exitFullscreen
(退出全屏),这两个 api 适用于 pc 和安卓端,但是 ios 不适用。ios 是个另类,只能用 webkitEnterFullscreen
api 进入全屏,而且,ios 是没有退出全屏的 api,进入全屏后,只能通过 iphone 的手势操作或自带控件进行退出全屏。
要注意以下几点:
webkitEnterFullscreen
只能对 ios 的 video 元素进行全屏,而且 ios 的全屏 api 只有webkitEnterFullscreen
,因此 ios 能够实现真正全屏的元素只有 video(下面有实现“假全屏”的代码)。requestFullscreen
是可以对几乎任何元素(不单止是 video)进行全屏。requestFullscreen
(进入全屏) 和exitFullscreen
(退出全屏)在不同的浏览器可能拥有独特的名称,如:mozRequestFullScreen
是火狐的 api。
下面直接贴出兼容各个浏览器(包括移动端)的播放器全屏代码示例,如果希望对非 video 元素进行全屏,把 toggleFullScreen 开头的 querySelector 指向目标元素,再稍微修改一下就可以使用了。
<!-- 最好有一个 div 包裹 video 标签 -->
<div class="video-box">
<video src="xxx" poster=""></video>
</div>
<script>
// 检测是否全屏(IOS 端无效)
function checkFullScreen() {
var isFull = document.webkitIsFullScreen || document.mozFullScreen ||
document.msFullscreenElement || document.fullscreenElement
if (isFull == null || isFull == undefined) {
isFull = false
}
return isFull
}
// 全屏
function toggleFullScreen() {
var videoBox = document.querySelector('.video-box')
// video 是 video-player 里面的 video 标签,这个用于 ios 端全屏
var video = document.querySelector('.video-box video')
var isFull = checkFullScreen()
//W3C
if (videoBox.requestFullscreen) {
isFull ? document.exitFullscreen() : videoBox.requestFullscreen()
}
//FireFox
else if (videoBox.mozRequestFullScreen) {
isFull ? document.mozCancelFullScreen() : videoBox.mozRequestFullScreen()
}
//Chrome
else if (videoBox.webkitRequestFullScreen) {
isFull ? document.webkitCancelFullScreen() : videoBox.webkitRequestFullScreen()
}
//IE11
else if (videoBox.msRequestFullscreen) {
isFull ? document.msExitFullscreen() : videoBox.msRequestFullscreen()
}
// IOS(特例)
else if (video.webkitEnterFullscreen) {
video.webkitEnterFullscreen()
}
// 这里可以做一些判断,更换全屏缩放图标(对 IOS 端没效果)
if (isFull) {
} else {
}
}
</script>
复制代码
全屏代码失效
iframe 引起
如果你的全屏代码是 iframe 页面里面的,记得 iframe 要允许全屏。
<iframe src="http://xxxx.com" allowfullscreen="allowfullscreen" mozallowfullscreen="mozallowfullscreen" msallowfullscreen="msallowfullscreen" oallowfullscreen="oallowfullscreen" webkitallowfullscreen="webkitallowfullscreen"></iframe>
复制代码
不是用户主动触发
如果你的全屏代码还是失效了,可能你做了这个操作:就是网页一打开,自动进行全屏,这个是会被浏览器禁止的。
全屏事件的触发只能由用户手动触发,即使你模拟鼠标自动点击也不行。
具体可以看看这个解释。
PC 端全屏后无法监听 ESC
通常来说,在 PC 端里,快捷键 ESC 也是可以退出全屏的。而当元素使用了 requestFullscreen API 进行全屏时,不需要写任何代码,ESC 键就会默认用来退出全屏,因此 ESC 键的监听会失效,如下代码会失效。
document.onkeydown = function() {
if (event.keyCode == 27) {
// 没任何作用
}
}
复制代码
看起来没什么问题,因为 ESC 键就是用来退出全屏呀!
但是有时候,我们可能会出现这种业务,退出全屏后需要立刻执行其他代码。
在这里,可以利用 onresize 曲线救国。当 window 发生大小变化时,检查是否是全屏状态,如果是退出全屏状态,则执行业务代码。
window.onresize = function () {
if (!checkFullScreen()) {
// 退出全屏后,执行业务代码
}
}
复制代码
播放器全屏后如何显示自定义控制条
视频全屏时也需要将控制条进行全屏,其实这个功能很简单,首先 video 标签需要一个父元素 video-box,我们要对 video-box 进行全屏,而不是 video 元素进行全屏,这样 video-box 里面的所有元素也都会进行全屏。而自定义控制条 ctrl-box 写到 video-box 里面即可。
<div class="video-box">
<video src="xxx" poster=""></video>
<!-- 自定义控制条 -->
<div class="ctrl-box">
...
</div>
</div>
复制代码
移动端全屏后无法显示自定义控制条
ios 端全屏后无法显示自定义控制条
由于 IOS 端的全屏只能调用 webkitEnterFullscreen 将 video 标签进行全屏(其实就是 IOS 端内置的全屏),全屏时是不能显示自定义的控制条。
再次提醒,webkitEnterFullscreen
是针对 ios 的 video 标签进行全屏,无法对其他元素进行全屏。
我们可以用样式写一个“假全屏”代码,避开使用 ios 控件,即可显示自定义控制条。
<script>
// 为了方便,下面用了 jq
// 判断是否是 IOS 端
var isIOS = !(navigator.userAgent.indexOf("Android") > -1) && (/Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent))
function toggleFullscreen() {
if ($('.video-box').hasClass('fullscreen')) {
// 这里设死高度 210 了,可以自己更改
$('.video-box').removeClass('fullscreen').removeClass('transform').width('100%').height(210).css('margin', '0')
} else {
$('.video-box').addClass('fullscreen')
if ($(window).width() < $(window).height() && isIOS) {
$('.video-box').width($(window).height()).height($(window).width()).css('margin', '-' + $(window).width()/2 + 'px 0 0 -' + $(window).height()/2 + 'px').addClass('transform')
}else{
$('.video-box').width($(window).width()).height($(window).height()).css('margin', '-' + $(window).height()/2 + 'px 0 0 -' + $(window).width()/2 + 'px')
}
}
}
// 重力感应,改变屏幕方向,如果是全屏时,也进行相应的改变
window.onresize = function() {
if($('.video-box').hasClass('fullscreen')){
if ($(window).width() < $(window).height() && isIOS) {
$('.video-box').width($(window).height()).height($(window).width()).css('margin', '-' + $(window).width()/2 + 'px 0 0 -' + $(window).height()/2 + 'px').addClass('transform')
}else{
$('.video-box').width($(window).width()).height($(window).height()).css('margin', '-' + $(window).height()/2 + 'px 0 0 -' + $(window).width()/2 + 'px').removeClass('transform')
}
}
}
</script>
<style>
/* 屏幕旋转的样式 */
.video-box.fullScreen.transform {
transform: rotate(90deg);
-ms-transform: rotate(90deg);
-webkit-transform: rotate(90deg);
-o-transform: rotate(90deg);
-moz-transform: rotate(90deg);
transform-origin: 50%;
-ms-transform-origin: 50%;
-webkit-transform-origin: 50%;
-moz-transform-origin: 50%;
-o-transform-origin: 50%;
}
/* 屏幕改变方向时,播放器控制条,需要固定 */
.video-box.fullScreen.transform .control {
position: fixed;
}
/* 全屏需要更改位置 */
.video-box.fullScreen {
position: fixed;
top: 50%;
left: 50%;
z-index: 10000;
}
</style>
复制代码
“假全屏”也兼容 android 端。
如果要用“假全屏”,记得把手机的重力感应开启,效果更佳。
“假全屏”的原理很简单,将指定元素 fixed,再将元素放大至 window 同样的宽高,再监测 resize 以至于监测重力感应做出对应改变。
不过这种方式存在一些体验问题,在 iphone 里,地址栏还是会存留在那里。如下图的红框部分:
android 端全屏后无法显示自定义控制条
在 android 端里,因为比较开放,不像 ios 的浏览器只能用 ios 的浏览器内核,android 的浏览器可谓是百花齐放,有各种各样的自定义功能。其中,有个对开发者不友好的情况是某些浏览器(如:QQ浏览器、uc浏览器)会自动隐藏掉我们自定义的控制条,改用浏览器内置的默认控制条(其实不单止是全屏,非全屏也一样)。
我想说的是……这个是无解的!!!!!!
至于为什么像虎牙直播可以显示自己的控制条,我怀疑是虎牙直播和浏览器可能进行了 py 交易!!!
在我之前写的文章:播放器 – 无法自动播放里,就已经提到过了,浏览器厂商有一个域名白名单的东西,填进去的网站可以自动播放。
在这里,也是同理的,在白名单的域名下的网站可以显示自己的控制条。不信,可以试试改 host,将虎牙的域名指向自己的网站,开代理,android 手机填好代理,用 android 上的 qq 浏览器打开虎牙的域名,你可以发现自己的网站也可以显示自己的控制条了(大家可以用 fiddler 软件开代理进行测试)。
在思否平台里,我还特别提问了这个问题“移动端网页播放器非全屏以及全屏时如何屏蔽浏览器默认的按钮和样式?”。
从技术层面来说,这个问题是无解的,各位技术淫不要再折腾了,除非你真的要和浏览器厂商进行 py 交易……