Web全屏模式

转自 Web全屏模式轻松掌握

CodePen Demo

地址:演示code

进去看看,玩一下,本文将结合这个demo一起进行讲解。

全屏功能封装在一个类里面:

我把全屏模式封装在一个类里面,在代码中有详细的注释,如果有需要的话,直接把类拿出来,根据栗子和注释使用即可。

代码在codepen的demo里。

何谓全屏?

MDN介绍

使用提供的API,让一个元素与其子元素,可以占据整个屏幕,并在此期间,从屏幕上隐藏所有的浏览器用户界面以及其他应用。

chrome下的全屏表现

全屏会隐藏标签栏,书签栏

如果网页一开始不是全部撑开的形式,全屏下,也会将要全屏的元素充满整个屏幕

可以多层全屏,如栗子中一样,可以先左边全屏,然后红色全屏。

在这种情况下退出全屏,只会退出红色全屏,退回到左边全屏的形式,所以页面依然是全屏模式。

进入全屏时,有一个默认的提示:'按esc即可退出全屏模式',如下图显示: ![](data:image/svg+xml;utf8,<?xml version="1.0"?><svg xmlns="www.w3.org/2000/svg" version="1.1" width="1280" height="131"></svg>) 5. 当按Esc或调用退出全屏方法,退出全屏。标签栏和书签栏依然是隐藏的,网页上的元素恢复成原本的尺寸

要显示书签栏和标签栏,需要刷新一下页面。


全屏API:

总共用到6个API

  1. 浏览器是否支持全屏模式:document.fullscreenEnabled
  2. 使元素进入全屏模式:Element.requestFullscreen()
  3. 退出全屏:document.exitFullscreen()
  4. 检查当前是否有节点处于全屏状态:document.fullscreenElement
  5. 进入全屏/离开全屏,触发事件:document.fullscreenchange
  6. 无法进入全屏时触发: document.fullscreenerror

浏览器前缀:

目前并不是所有的浏览器都实现了API的无前缀版本,所以我们需要针对不同浏览器,做一下API的兼容:

这是我在demo中做的浏览器兼容:

/**
 * @description: 是否支持全屏+判断浏览器前缀
 * @param {Function} fn 不支持全屏的回调函数 这里设了一个默认值
 */
isFullscreen(fn) {
  let fullscreenEnabled;
  // 判断浏览器前缀if (document.fullscreenEnabled) {
    fullscreenEnabled = document.fullscreenEnabled;
  } elseif (document.webkitFullscreenEnabled) {
    fullscreenEnabled = document.webkitFullscreenEnabled;
    this.prefixName = 'webkit';
  } elseif (document.mozFullScreenEnabled) {
    fullscreenEnabled = document.mozFullScreenEnabled;
    this.prefixName = 'moz';
  } elseif (document.msFullscreenEnabled) {
    fullscreenEnabled = document.msFullscreenEnabled;
    this.prefixName = 'ms';
  }
  if (!fullscreenEnabled) {
    if (fn !== undefined) fn(); // 执行不支持全屏的回调this.isFullscreenData = false;
  }
}
复制代码
复制代码

我在实例化的时候进行一次判断浏览器是否支持全屏,然后保存浏览器前缀

推荐这么做,因为如果每个API都要这样重复的判断浏览器前缀,那也太恶心了!

1. 浏览器是否支持全屏模式:document.fullscreenEnabled

document.fullscreenEnabled属性返回一个布尔值,表示当前文档是否可以切换到全屏状态。

代码在上方浏览器前缀代码中给出了。

如果没有保存浏览器前缀的话,注意做一下不同浏览器前缀的兼容!下面不再强调

2. 使元素进入全屏模式:Element.requestFullscreen()

/**
 * @description: 将传进来的元素全屏
 * @param {String} domName 要全屏的dom名称
 */
Fullscreen(domName) {
  const element = document.querySelector(domName); // 获取domconst methodName =
    this.prefixName === ''
      ? 'requestFullscreen'
      : `${this.prefixName}RequestFullScreen`; // API前缀
  element[methodName](); // 调用全屏
}
复制代码
复制代码

这就是我们实现全屏的API,是不是超简单?

值得注意的是:调用此API并不能保证元素一定能够进入全屏模式

MDN:例如<iframe> 元素具有 allowfullscreen 属性,可选择是否将其内容以全屏模式显示

这种不被允许全屏的元素属于极少数情况,我试过可以将button全屏。

全屏请求必须在事件处理函数(点击事件等)中调用,否则将会被拒绝。

demo中有演示,初始化直接全屏,会触发进入全屏失败回调。

3. 退出全屏:document.exitFullscreen()

介绍

exitFullscreen() {
  const methodName =
    this.prefixName === ''
      ? 'exitFullscreen'
      : `${this.prefixName}ExitFullscreen`; // API 前缀document[methodName](); // 调用
}
复制代码
复制代码

调用这个方法会让文档回退到上一个调用Element.requestFullscreen()方法进入全屏模式之前的状态。

多层全屏

demo中,先进入左边全屏,再进入红色全屏,即为:多层全屏的情况(虽然这种情况并不多)。

当出现多层全屏的情况,需要一层层的退出到页面最初始的情况,并不是调用一次document.exitFullscreen()就恢复到页面最初始的样子。

4. 检查当前是否有节点处于全屏状态:document.fullscreenElement

fullscreenElement属性返回正处于全屏状态的Element节点,如果当前没有节点处于全屏状态,则返回null

/**
 * @description: 检测有没有元素处于全屏状态
 * @return 布尔值
 */
isElementFullScreen() {
  const fullscreenElement =
    document.fullscreenElement ||
    document.msFullscreenElement ||
    document.mozFullScreenElement ||
    document.webkitFullscreenElement; // 有前缀的f是大写,没前缀是小写if (fullscreenElement === null) {
    returnfalse; // 当前没有元素在全屏状态
  } else {
    returntrue; // 有元素在全屏状态
  }
}
复制代码
复制代码

事实上,还有一个属性document.fullscreen,返回一个布尔值,表示文档是否处于全屏模式。

两个方法效果是一样,但因为IE不支持这个属性,所以这里用的是document.fullscreenElement

5. 进入全屏/离开全屏,触发事件:document.fullscreenchange

当我们进入全屏和离开全屏的时候,都会触发一个fullscreenchange事件。

MDN注意:此事件不会提供任何信息,表明是进入全屏或退出全屏

看了好久事件返回的信息,确实找不到一个值,表明这是在进入全屏,或者离开全屏!

可以说相当不人性化了!但我们可以通过检查当前是否有节点处于全屏状态,判断当前是否处于全屏模式。

/**
 * @description: 监听进入/离开全屏
 * @param {Function} enter 进入全屏的回调
 *  @param {Function} quit 离开全屏的回调
 */
screenChange(enter,quit) {
  if (!this.isFullscreenData) return;
  const methodName = `on${this.prefixName}fullscreenchange`;
  document[methodName] = e => {
    if (this.isElementFullScreen()) {
      enter && enter(e); // 进入全屏回调
    } else {
      quit && quit(e); // 离开全屏的回调
    }
  };
}
复制代码
复制代码

注意:多层全屏的情况

  1. 先进入左边全屏(进入全屏回调),再进入红色全屏(进入全屏回调)
  2. 退出全屏,此时退出红色全屏,左边仍是全屏(触发进入全屏回调)
  3. 出现这种情况,可以在点击按钮的时候,做一些状态限制。或者根据全屏事件返回的dom信息来进行判断。

6. 无法进入全屏时触发: document.fullscreenerror

进入全屏并不总是成功的,可能是技术原因,也可能是用户拒绝,我们在上文进入全文的APIElement.requestFullscreen()部分讲过了。

比如全屏请求不是在事件处理函数中调用,会在这里拦截到错误

/**
 * @description: 浏览器无法进入全屏时触发
 * @param {Function} enterErrorFn 回调
 */
screenError(enterErrorFn) {
  const methodName = `on${this.prefixName}fullscreenerror`;
  document[methodName] = e => {
    enterErrorFn && enterErrorFn(e)
  };
}
复制代码
复制代码

Css: 全屏模式下的样式

chorme 70 下的默认会为正在全屏的dom添加两个class:稍微看一下

  1. 默认设置黑色背景

    :not(:root):-webkit-full-screen::backdrop { position: fixed; top: 0px; right: 0px; bottom: 0px; left: 0px; background: black; // 会将背景设为黑色的 如果你没为你的dom设置背景的话,全屏下会为黑色 } 复制代码

  2. 默认样式:

    :not(:root):-webkit-full-screen { object-fit: contain; position: fixed !important; top: 0px!important; right: 0px!important; bottom: 0px!important; left: 0px!important; box-sizing: border-box !important; min-width: 0px!important; max-width: none !important; min-height: 0px!important; max-height: none !important; width: 100%!important; height: 100%!important; transform: none !important; margin: 0px!important; } 复制代码

全屏状态的CSS:

全屏状态下,大多数浏览器的CSS支持:full-screen伪类,只有IE11支持:fullscreen伪类。使用这个伪类,可以对全屏状态设置单独的CSS属性。

以下css摘自阮一峰老师的Fullscreen API:全屏操作

/* 针对dom的全屏设置 */.div:-webkit-full-screen {
  background: #fff;
}
/* 全屏属性 */:-webkit-full-screen {}
:-moz-full-screen {}
:-ms-fullscreen {}
/* 全屏伪类 当前chrome:70 不支持 */:full-screen {
}
:fullscreen {
  /* IE11支持 */
}
复制代码
复制代码

完整DEMO


<!DOCTYPE html>
<html>

	<head>
		<meta charset="UTF-8">
		<title></title>
		<style type="text/css">
			.top {
				margin: 15px;
			}
			
			.main {
				width: 100%;
				height: 1000px;
				display: flex;
			}
			
			.left {
				width: 50%;
				height: 60%;
				background: gray;
				padding: 20px;
			}
			
			.left-son {
				width: 80%;
				height: 50%;
				margin: 15px;
				background: red;
			}
			
			.right {
				width: 50%;
				height: 60%;
				background: #dddddd;
			}
			/* 针对dom的全屏设置 */
			
			.left:-webkit-full-screen {
				background: #fff;
			}
			/* 全屏属性 */
			
			:-webkit-full-screen {}
			
			:-moz-full-screen {}
			
			:-ms-fullscreen {}
			/* 全屏伪类 当前chrome:70 不支持 */
			
			:full-screen {}
			
			:fullscreen {
				/* IE11支持 */
			}
		</style>
	</head>

	<body>

		<div class="top">
			<button onclick="leftScreen()">左边全屏</button>
			<button onclick="rightScreen()">右边全屏</button>
		</div>
		<div class="main">
			<div class="left">
				<button onclick="redScreen()">红色全屏</button>
				<button onclick="exitScreen()">退出全屏</button>
				<div class="left-son">
					<button onclick="exitScreen()">红色退出全屏</button>
					<span>左边的内容</span>
				</div>
			</div>
			<div class="right">右边的内容</div>
		</div>
	</body>
	<script type="text/javascript">
		class fullScreen {
			/**
			 * @description: 全屏初始化
			 * @param {Function} fn 用户浏览器不支持全屏的回调
			 */
			constructor(fn) {
				this.prefixName = ""; // 浏览器前缀
				this.isFullscreenData = true; // 浏览器是否支持全屏
				this.isFullscreen(fn);
			}
			/**
			 * @description: 将传进来的元素全屏
			 * @param {String} domName 要全屏的dom名称
			 */
			Fullscreen(domName) {
				const element = document.querySelector(domName);
				const methodName =
					this.prefixName === "" ?
					"requestFullscreen" :
					`${this.prefixName}RequestFullScreen`;
				element[methodName]();
			}
			// 退出全屏
			exitFullscreen() {
				const methodName =
					this.prefixName === "" ?
					"exitFullscreen" :
					`${this.prefixName}ExitFullscreen`;
				document[methodName]();
			}
			/**
			 * @description: 监听进入/离开全屏
			 * @param {Function} enter 进入全屏的回调
			 *  @param {Function} quit 离开全屏的回调
			 */
			screenChange(enter, quit) {
				if(!this.isFullscreenData) return;
				const methodName = `on${this.prefixName}fullscreenchange`;
				document[methodName] = e => {
					if(this.isElementFullScreen()) {
						enter && enter(e); // 进入全屏回调
					} else {
						quit && quit(e); // 离开全屏的回调
					}
				};
			}
			/**
			 * @description: 浏览器无法进入全屏时触发,可能是技术原因,也可能是用户拒绝:比如全屏请求不是在事件处理函数中调用,会在这里拦截到错误
			 * @param {Function} enterErrorFn 回调
			 */
			screenError(enterErrorFn) {
				const methodName = `on${this.prefixName}fullscreenerror`;
				document[methodName] = e => {
					enterErrorFn && enterErrorFn(e);
				};
			}
			/**
			 * @description: 是否支持全屏+判断浏览器前缀
			 * @param {Function} fn 不支持全屏的回调函数 这里设了一个默认值
			 */
			isFullscreen(fn) {
				let fullscreenEnabled;
				// 判断浏览器前缀
				if(document.fullscreenEnabled) {
					fullscreenEnabled = document.fullscreenEnabled;
				} else if(document.webkitFullscreenEnabled) {
					fullscreenEnabled = document.webkitFullscreenEnabled;
					this.prefixName = "webkit";
				} else if(document.mozFullScreenEnabled) {
					fullscreenEnabled = document.mozFullScreenEnabled;
					this.prefixName = "moz";
				} else if(document.msFullscreenEnabled) {
					fullscreenEnabled = document.msFullscreenEnabled;
					this.prefixName = "ms";
				}
				if(!fullscreenEnabled) {
					this.isFullscreenData = false;
					fn && fn(); // 执行不支持全屏的回调
				}
			}
			/**
			 * @description: 检测有没有元素处于全屏状态
			 * @return 布尔值
			 */
			isElementFullScreen() {
				const fullscreenElement =
					document.fullscreenElement ||
					document.msFullscreenElement ||
					document.mozFullScreenElement ||
					document.webkitFullscreenElement;
				if(fullscreenElement === null) {
					return false; // 当前没有元素在全屏状态
				} else {
					return true; // 有元素在全屏状态
				}
			}
		}
		let full = new fullScreen(() => {
			console.log("不支持");
		});
		full.screenError(e => {
			console.log("进去全屏失败:", e);
		});
		// 全屏请求必须在事件处理函数中调用,否则将会被拒绝。
		full.Fullscreen(".left"); // 触发进去全屏失败回调
		const obj = {
			enter: e => {
				// 如果退出全屏 退出的还是全屏状态,将会触发进入全屏的回调,这种情况比较少 注意一下
				console.log("进入全屏", e);
			},
			quit: e => {
				console.log("退出全屏", e);
				// 通常不会出现嵌套的情况
			}
		};
		full.screenChange(obj.enter, obj.quit);

		function leftScreen() {
			full.Fullscreen(".left");
		}

		function rightScreen() {
			full.Fullscreen(".right");
		}

		function redScreen() {
			full.Fullscreen(".left-son");
		}
		// 退出全屏 退出到上次的状态
		function exitScreen() {
			full.exitFullscreen();
		}
	</script>

</html>
复制代码

结语

我们可以把全屏技术应用在H5游戏、信息流网站、视频等地方,下次再有全屏需求时,记住不要慌,回头看看过本文的栗子,把我封装的类拿出来直接用就可以啦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值