运行环境:
EDGE浏览器120.0.2210.144 (正式版本) (64 位);
谷歌版本 121.0.6167.85(正式版本)(64 位);
dependencies: {
"vue": "^3.3.4"
},
"devDependencies": {
"@types/node": "^20.11.4",
"@vitejs/plugin-vue": "^4.2.3",
"typescript": "^5.0.2",
"vite": "^4.4.5",
"vite-plugin-require-transform": "^1.0.21",
"vue-tsc": "^1.8.5"
}
问题:
作者本来想做一个需求,就是按F11浏览器全屏,隐藏一个东西;再按一下显示出来,结果事与愿违,下面敲重点!
下面讲通过EDGE浏览器和chrome浏览器按F11全屏的形式
1)onresize(网上的方法来监听全屏切换)执行两次,F11切回非全屏执行一次。
2)keydown事件再按F11退出无法触发对应keydown事件(按F11全屏可以监听到)。更恶心的是获取当前浏览器全屏状态(isFullScreen方法)一直都是false状态(非全屏)(ˉ▽ˉ;)...
onMounted(()=>{
//注册监听
console.log("mounted")
window.addEventListener("keydown", keydown, true)// 监听按键事件
})
onBeforeUnmount(()=>{
console.log("unmount")
window.removeEventListener("keydown", keydown, true)// 移除监听按键事件
})
window.onresize = function (){
console.log("resize")
if(isFullScreen()){
alert("全屏")
}else{
alert("非全屏")
}
}
function isFullScreen() {
return (
(document.fullscreenElement && document.fullscreenElement !== null) ||
(document.webkitFullscreenElement && document.webkitFullscreenElement !== null) ||
(document.mozFullScreenElement && document.mozFullScreenElement !== null) ||
(document.msFullscreenElement && document.msFullscreenElement !== null)
);
//如果没封装,document.webkitFullscreenElement等其它浏览器内核会变红。
}
特别说一下 ts不支持webkitFullscreenElement,mozFullScreenElement等属性,因此在编写过程中会有报错。
解决方法:在自己的.d.ts文件中可以对ts系统自带的interface进行声明合并(扩展);(作者放在vite-env.d.ts文件中)
/// <reference types="vite/client" />
// 注册其他浏览器内核方法
interface HTMLElement {
// 进入全屏
webkitRequestFullscreen(options?: FullscreenOptions): Promise<void>;
webkitRequestFullScreen(options?: FullscreenOptions): Promise<void>;
msRequestFullscreen(options?: FullscreenOptions): Promise<void>;
mozRequestFullScreen(options?: FullscreenOptions): Promise<void>;
// 监听全屏
onwebkitfullscreenchange: ((this: Element, ev: Event) => any) | null;
onmozfullscreenchange: ((this: Element, ev: Event) => any) | null;
MSFullscreenChange: ((this: Element, ev: Event) => any) | null;
}
interface Document {
// 当前全屏的元素
readonly webkitFullscreenElement: Element | null;
readonly msFullscreenElement: Element | null;
readonly mozFullScreenElement: Element | null;
// 退出全屏
webkitExitFullscreen(): Promise<void>;
msExitFullscreen(): Promise<void>;
mozCancelFullScreen(): Promise<void>;
}
解决方案:
改用按钮点击的形式进行浏览器全屏状态切换。
useFullScreen.ts:
type RFSMethodName = 'webkitRequestFullScreen' | 'requestFullscreen' | 'msRequestFullscreen' | 'mozRequestFullScreen';
type EFSMethodName = 'webkitExitFullscreen' | 'msExitFullscreen' | 'mozCancelFullScreen' | 'exitFullscreen';
type FSEPropName = 'webkitFullscreenElement' | 'msFullscreenElement' | 'mozFullScreenElement' | 'fullscreenElement';
type ONFSCPropName = 'onfullscreenchange' | 'onwebkitfullscreenchange' | 'onmozfullscreenchange' | 'MSFullscreenChange';
/**
* caniuse
* https://caniuse.com/#search=Fullscreen
* 参考 MDN, 并不确定是否有o前缀的, 暂时不加入
* https://developer.mozilla.org/zh-CN/docs/Web/API/Element/requestFullscreen
* 各个浏览器
* https://www.wikimoe.com/?post=82
*/
const DOC_EL = document.documentElement;
let RFC_METHOD_NAME: RFSMethodName = 'requestFullscreen';
let EFS_METHOD_NAME: EFSMethodName = 'exitFullscreen';
let FSE_PROP_NAME: FSEPropName = 'fullscreenElement';
let ON_FSC_PROP_NAME: ONFSCPropName = 'onfullscreenchange';
if (`webkitRequestFullScreen` in DOC_EL) {
RFC_METHOD_NAME = 'webkitRequestFullScreen';
EFS_METHOD_NAME = 'webkitExitFullscreen';
FSE_PROP_NAME = 'webkitFullscreenElement';
ON_FSC_PROP_NAME = 'onwebkitfullscreenchange';
} else if (`msRequestFullscreen` in DOC_EL) {
RFC_METHOD_NAME = 'msRequestFullscreen';
EFS_METHOD_NAME = 'msExitFullscreen';
FSE_PROP_NAME = 'msFullscreenElement';
ON_FSC_PROP_NAME = 'MSFullscreenChange';
} else if (`mozRequestFullScreen` in DOC_EL) {
RFC_METHOD_NAME = 'mozRequestFullScreen';
EFS_METHOD_NAME = 'mozCancelFullScreen';
FSE_PROP_NAME = 'mozFullScreenElement';
ON_FSC_PROP_NAME = 'onmozfullscreenchange';
} else if (!(`requestFullscreen` in DOC_EL)) {
throw `当前浏览器不支持Fullscreen API !`;
}
/**
* 启用全屏
* @param {HTMLElement} 元素
* @param {FullscreenOptions} 选项
* @returns {Promise}
*/
export function beFull(el: HTMLElement = DOC_EL, options?: FullscreenOptions): Promise<void> {
return el[RFC_METHOD_NAME](options);
}
/**
* 退出全屏
*/
export function exitFull(): Promise<void> {
return document[EFS_METHOD_NAME]();
}
/**
* 元素是否全屏
* @param {HTMLElement}
*/
export function isFull(el: HTMLElement | EventTarget): boolean {
return el === document[FSE_PROP_NAME]
}
/**
* 切换全屏/关闭
* @param {HTMLElement} 目标元素
* @returns {Promise}
*/
export function toggleFull(el: HTMLElement = DOC_EL, options?: FullscreenOptions): Promise<void> {
if (isFull(el)) {
return exitFull();
} else {
return beFull(el, options)
}
}
/**
* 当全屏/退出时触发
* @param {HTMLElement} 元素
* @param {(isFull: boolean) => void} 返回"是否全屏"
*/
export function watchFull(el: HTMLElement= DOC_EL, callback: (isFull: boolean) => void) {
const cancel = () => {
el.onfullscreenchange = null;
};
const handler = (event: Event) => {
if (null !== event.target) {
callback(isFull(event.target));
}
}
// 这里addEventListener不好使
el[ON_FSC_PROP_NAME] = handler;
return {
cancel
}
}
SPA组件应用代码:
<template>
<div class="y_rot" v-if="isLoaded">
isNotFullscreen:{{ isNotFullscreen }}
<select id="animate-list" v-model="selectedAnimate" v-show="isNotFullscreen">
<option value="" disabled selected hidden></option> <!-- 默认空白选项 -->
<option v-for="(item, index) in arrangeList" :key="index" :value="item.id">{{ item.name }}</option>
</select>
<button @click="toggle($event)">全屏切换</button>
</div>
</template>
<script setup lang="ts">
import { onBeforeUnmount,onMounted, reactive,ref } from 'vue';
import * as useFullscreen from './hooks/useFullscreen.ts';
let isNotFullscreen = ref(true);
let imgList= reactive(UserConfig);
let selectedAnimate = ref("");
let arrangeList = reactive([
{ name: '苹果', id: 'apple' },
{ name: '香蕉', id: 'banana' },
{ name: '芒果', id: 'mogo'}
]);
onMounted(()=>{
isLoaded.value = true;
// 获取需要全屏的元素
//注册监听
console.log("mounted")
window.addEventListener("keydown", keydown, true)// 监听按键事件
})
onBeforeUnmount(()=>{
console.log("unmount")
window.removeEventListener("keydown", keydown, true)// 移除监听按键事件
})
async function toggle(event:any){
await useFullscreen.toggleFull(document.documentElement as HTMLElement);
}
useFullscreen.watchFull(document.documentElement as HTMLElement,(isFull)=>{
console.log(isFull)
isNotFullscreen.value = !isFull;
//alert(isFullScreen());
})
async function keydown(event:any){
console.log(event.keyCode)
if (event.keyCode === 122) {
console.log("f11")
}
}
</script>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。