页面全屏实现与实现过程中遇到的问题(弹框不显示)
页面全屏实现与实现过程中遇到的问题(弹框不显示)
在日常的工作中,有些场景会需要实现全屏的效果,常见的全屏效果会分为全屏 以及页面全屏两种。
页面全屏
页面全屏就是只在浏览器视觉视口(浏览器可看到的区域)全屏。
实现
实现页面全屏的方式可以使用CSS的定位position: fixed和z-index实现。
.pageFullScreen {
position: fixed;
z-index: 10000;
left:0;
top: 0;
width:100%;
height: 100%;
}
上面的CSS可以实现页面全屏,但是还需要进行点击按钮的切换,在此使用vue实现。
// 在需要页面全屏的html标签中,使用v-bind绑定class,根据目前是否全屏的状态变量改变样式。
:class="{'pageFullScreen': bol}" // bol是目前是否全屏的状态变量
全屏
这种就是就是页面会占满整个屏幕,与浏览器大小无关,无论浏览器放大还是缩小都会占满整个屏幕,按ESC它可以退出全屏,如下图。
实现
想要实现占满全部屏幕有相应的API可以实现,下面可以看下相关代码。
// 进入全屏方法
export const enterFullscreen = (el) => {
// W3C
if (el.requestFullscreen) {
el.requestFullscreen();
}
// 火狐
else if (el.mozRequestFullScreen) {
el.mozRequestFullScreen();
}
// 谷歌
else if (el.webkitRequestFullScreen) {
el.webkitRequestFullScreen();
}
// IE
else if (el.msRequestFullscreen) {
el.msRequestFullscreen();
}
};
可以看到实现还是比较简单的,只要传需要全屏的DOM元素再调用API可以实现全屏效果了。
就算自己没有实现退出全屏,点击键盘ESC也是可以退出全屏的,不过最好还是自己再写一个方法实现退出全屏给按钮点击使用。
// 退出全屏方法
export const exitFullscreen = () => {
if (document.exitFullscreen) {
document.exitFullscreen();
}
else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
}
else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
}
else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
};
除此之外我们还可以检测当前是否是全屏状态,方便进行一些业务的判断。
// 检测是否全屏,根据返回的true或false判断,全屏:true,非全屏:false
export const isFullScreenStatus = () => {
return document.isFullScreen ||
document.mozIsFullScreen ||
document.webkitIsFullScreen;
};
以上就可以实现一个占满全部屏幕的效果了。
全屏中存在的问题
有时候我们在业务中需要的是页面中的某一部分实现全屏效果,实现这个其实只需要传入这部分的DOM元素就可以了,不过这有时候会造成一个问题,就是页面虽然全屏了,但是点击页面上的弹框或者下拉框这类组件却发现没有弹出来。
其实并不是这类组件点击了没有反应,而是这类弹框在的DOM并不在该全屏的DOM下,而是在body下,而全屏的情况下DOM的层级是最高的 (设置z-index都无济于事) ,因此不在全屏DOM下的弹框类组件弹出来了也会被全屏给覆盖,导致了就算是弹框已弹出来了也看不到。
比如element ui库的 Dialog 对话框组件在使用append-to-body这个属性时对话框组件的DOM就是在body下面;在后面统一用body弹框表示这类组件。
解决方案
以下的代码是Vue3的语法。
方案一
解决此问题的方法最好就是将该类型组件的DOM加到需要全屏的元素下,这种合适body弹框较少的页面。
具体实现
点击打开弹框的按钮时执行以下代码。
// 关键代码
nextTick(() => {
dialogTableVisible.value = true // 示例:打开Dialog对话框,具体根据自己情况调整
if (document.querySelector('.el-overlay')) {
// 将Dialog的DOM元素添加到需要全屏的元素下,这是我的示例,具体根据自己情况调整
panelRef.value.appendChild(document.querySelector('.el-overlay'));
}
})
方案二
上面的方案比较合适body弹框较少的页面,如果是碰到body弹框较多或者是页面中引入了其他组件,在这些组件中存在着不知数量的body弹框,那么方案一的工作量就会变得比较多比较复杂。
方案二可以使用页面全屏加上全屏实现。
思路:首先将需要全屏的DOM实现页面全屏,再将body实现全屏,这样就算body弹框是在body下也可以显示出来。
具体实现
需要注意监听窗口的变化以及键盘F11的全屏冲突,注意看代码中的注释
<script setup>
import { ref, reactive, onMounted, nextTick } from 'vue'
// 这部分方法的代码上面已经有了
import { enterFullscreen, exitFullscreen, isFullScreenStatus } from './js/index'
name: 'fullScreen'
let bol = ref(false)
const panelRef = ref(null) // 获取全屏元素的ref
onMounted(() => {
window.addEventListener("keydown", keydown, true); //监听键盘按钮
window.addEventListener('resize', resize) // 监听窗口大小变化
})
// 监听窗口大小变化,执行回调,当全屏状态按键盘ESC时会退出全屏状态,这时也要退出页面全屏状态
// 不监听键盘ESC事件是因为全屏状态时,点击键盘ESC不触发该按键的事件监听
const resize = () => {
if (!isFullScreenStatus()) {
bol.value = false // 退出页面全屏状态
}
}
//监听键盘按钮,执行回调,为了防止与键盘F11的全屏冲突
const keydown = (e) => {
if (e.keyCode === 122) { // 键盘F11的码
e.returnValue = false // 阻止F11原本的全屏事件
onPageFullScreen() // 触发自己实现的全屏的方法
}
}
// 全屏按钮函数
const onPageFullScreen = () => {
if(bol.value) {
exitFullscreen() // 退出全屏
}
if(!isFullScreenStatus()) {
// 全屏
enterFullscreen(document.querySelector('body')) // 获取body的DOM传递给全屏方法实现全屏
bol.value = !bol.value
}
}
</script>
总结
这些都是本人在项目中的需求实现与遇到的问题,不一定适用全部人,不过如果有适用的场景可以借鉴一下,代码写的一般,可以借鉴思路。
转载自:https://juejin.cn/post/7210387904748191799