全屏解决方案:原生、screenfull、useFullscreen,我该用哪个?

您所在的位置:网站首页 sai进入全屏 全屏解决方案:原生、screenfull、useFullscreen,我该用哪个?

全屏解决方案:原生、screenfull、useFullscreen,我该用哪个?

2023-07-25 16:57| 来源: 网络整理| 查看: 265

vue项目中有一个全屏功能,我该怎么办?本文结合实际的vue项目介绍了浏览器原生的全屏API、 screenfull、useFullscreen的用法并结合源码分析了screenfull和useFullscreen的原理,欢迎阅读学习。

1.原生requestFullScreen等

原生的全屏API有如下几个:

(1)Element.requestFullscreen():用于发出异步请求使元素进入全屏模式;

(2)Document.exitFullscreen() :用于让当前文档退出全屏模式;

(3)fullscreen: 只读属性,报告文档当前是否以全屏模式显示内容;

(4)fullscreenElement: 当前文档中正在以全屏模式显示的节点,如果没有使用全屏模式,则返回null;

(5)allowfullscreen:是否允许激活全屏模式。

更多详细内容可以参照MDN。如下代码是笔者项目中用到的一段代码:

fullScreen() { if (this.$refs['cells'].requestFullScreen) { this.$refs['cells'].requestFullScreen() } else if (this.$refs['cells'].mozRequestFullScreen) { this.$refs['cells'].mozRequestFullScreen() } else if (this.$refs['cells'].webkitRequestFullScreen) { this.$refs['cells'].webkitRequestFullScreen() } }, 2.screenfull的使用 2.1 简介

screenfull对各种浏览器全屏的API进行封装,以便于我们可以方便的使页面或者元素切换到全屏状态。例如:

使页面切换到全屏:

import screenfull from 'screenfull'; document.getElementById('button').addEventListener('click', () => { if (screenfull.isEnabled) { screenfull.request(); } else { // Ignore or do something else } });

使元素切换到全屏:

import screenfull from 'screenfull'; const element = document.getElementById('target'); document.getElementById('button').addEventListener('click', () => { if (screenfull.isEnabled) { screenfull.request(element); } });

screenfull有如下常用的API:

.request(element, options?) 使元素或者页面切换到全屏;

.exit()退出全屏;

.toggle(element, options?)在全屏和非全屏之间切换;

.on(event, function)监听全屏切换或者错误事件;

.off(event, function)移除之前注册的事件监听;

.isFullscreen 现在是否为全屏;

.isEnabled 浏览器是否允许全屏。

2.2 使用

element-plus-admin中使用了screenfull, 并封装为单独的组件:

import { defineComponent, ref, onMounted, onUnmounted } from 'vue' import screenfull from 'screenfull' import { ElNotification } from 'element-plus' export default defineComponent({ name: 'Screenfull', setup() { const isFullscreen = ref(false) const changeScreenfull = () => { if (!screenfull.isEnabled) { ElNotification({ message: '浏览器不支持全屏', type: 'warning' }) }else{ screenfull.toggle() } } const change = () => { if(screenfull.isEnabled) isFullscreen.value = screenfull.isFullscreen } onMounted(() => screenfull.isEnabled && screenfull.on('change', change)) onUnmounted(() => screenfull.isEnabled && screenfull.off('change', change)) return { isFullscreen, changeScreenfull } } }) 2.3 screenfull原理

下面我们通过screenful的源码了解一下其原理。

2.3.1 methodMap

首先定义了一个由不同浏览器全屏相关的方法组成的数组:

const methodMap = [ [ 'requestFullscreen', 'exitFullscreen', 'fullscreenElement', 'fullscreenEnabled', 'fullscreenchange', 'fullscreenerror', ], // New WebKit [ 'webkitRequestFullscreen', 'webkitExitFullscreen', 'webkitFullscreenElement', 'webkitFullscreenEnabled', 'webkitfullscreenchange', 'webkitfullscreenerror', ], // Old WebKit [ 'webkitRequestFullScreen', 'webkitCancelFullScreen', 'webkitCurrentFullScreenElement', 'webkitCancelFullScreen', 'webkitfullscreenchange', 'webkitfullscreenerror', ], [ 'mozRequestFullScreen', 'mozCancelFullScreen', 'mozFullScreenElement', 'mozFullScreenEnabled', 'mozfullscreenchange', 'mozfullscreenerror', ], [ 'msRequestFullscreen', 'msExitFullscreen', 'msFullscreenElement', 'msFullscreenEnabled', 'MSFullscreenChange', 'MSFullscreenError', ], ]; 2.3.2 nativeAPI

nativeAPI方法用于检查浏览器支持的全屏相关方法,代码详细分析见注释:

const nativeAPI = (() => { // 无浏览器前缀的方法名数组 const unprefixedMethods = methodMap[0]; const returnValue = {}; // 遍历methodMap的每一个元素 for (const methodList of methodMap) { // 是否可以退出全屏 const exitFullscreenMethod = methodList?.[1]; // 检查document上是否存在可以退出全屏的方法 if (exitFullscreenMethod in document) { // 如果支持全屏,则把相关方法都注册到returnValue上 for (const [index, method] of methodList.entries()) { returnValue[unprefixedMethods[index]] = method; } return returnValue; } } return false; })(); 2.3.3 eventNameMap

eventNameMap定义全屏状态切换和全屏发生错误的事件映射:

const eventNameMap = { change: nativeAPI.fullscreenchange, error: nativeAPI.fullscreenerror, }; 2.3.4 request

screenfull对象上定义了一些全屏方法, 首先看一下request方法:

request(element = document.documentElement, options) { return new Promise((resolve, reject) => { // 全屏触发的方法 const onFullScreenEntered = () => { // 取消注册进入全屏的事件 screenfull.off('change', onFullScreenEntered); resolve(); }; // 注册进入全屏的事件 screenfull.on('change', onFullScreenEntered); // 执行原生的进入全屏的方法,返回值为promise const returnPromise = element[nativeAPI.requestFullscreen](options); if (returnPromise instanceof Promise) { returnPromise.then(onFullScreenEntered).catch(reject); } }); },

request用于发起全屏请求,返回值为一个promise。

2.3.5 exit

exit方法用于退出全屏,具体逻辑和请求全屏类似:

exit() { return new Promise((resolve, reject) => { if (!screenfull.isFullscreen) { resolve(); return; } // 退出全屏触发的方法 const onFullScreenExit = () => { screenfull.off('change', onFullScreenExit); resolve(); }; // 退出全屏触发的事件 screenfull.on('change', onFullScreenExit); // 执行退出全屏的方法 const returnPromise = document[nativeAPI.exitFullscreen](); if (returnPromise instanceof Promise) { returnPromise.then(onFullScreenExit).catch(reject); } }); }, 2.3.6 事件相关的方法 onchange(callback) { screenfull.on('change', callback); }, onerror(callback) { screenfull.on('error', callback); }, on(event, callback) { const eventName = eventNameMap[event]; if (eventName) { document.addEventListener(eventName, callback, false); } }, off(event, callback) { const eventName = eventNameMap[event]; if (eventName) { document.removeEventListener(eventName, callback, false); } }

on方法用于注册事件,off用于取消事件,onchange和onerror分别用于注册全

3.useFullscreen的使用 3.1 简介

useFullscreen是vueuse核心提供的全屏功能。官方文档给出了如下图所示的例子:

点击fullscreen按钮可以进入全屏模式,实现代码如下图所示:

import { ref } from 'vue' import { useFullscreen } from '@vueuse/core' const el = ref(null) const { toggle, isFullscreen } = useFullscreen(el) Go Fullscreen

引入了useFullscreen来控制el(即video元素)的全屏,使用到了toggle方法和isFullscreen这个响应式的变量。

3.2 使用

vue-element-plus-admin 中使用了useFullscreen:

import { Icon } from '@/components/Icon' import { useFullscreen } from '@vueuse/core' import { propTypes } from '@/utils/propTypes' import { useDesign } from '@/hooks/web/useDesign' const { getPrefixCls } = useDesign() const prefixCls = getPrefixCls('screenfull') defineProps({ color: propTypes.string.def('') }) const { toggle, isFullscreen } = useFullscreen() const toggleFullscreen = () => { toggle() }

引入了useFullscreen来控制页面的全屏,使用到了toggle方法和isFullscreen这个响应式的变量。

3.3 useFullscreen原理

和screenfull类似,首先定义了一个由不同浏览器全屏相关的方法组成的数组functionsMap:

type FunctionMap = [ 'requestFullscreen', 'exitFullscreen', 'fullscreenElement', 'fullscreenEnabled', 'fullscreenchange', 'fullscreenerror', ] const functionsMap: FunctionMap[] = [ [ 'requestFullscreen', 'exitFullscreen', 'fullscreenElement', 'fullscreenEnabled', 'fullscreenchange', 'fullscreenerror', ], // New WebKit [ 'webkitRequestFullscreen', 'webkitExitFullscreen', 'webkitFullscreenElement', 'webkitFullscreenEnabled', 'webkitfullscreenchange', 'webkitfullscreenerror', ], // Old WebKit [ 'webkitRequestFullScreen', 'webkitCancelFullScreen', 'webkitCurrentFullScreenElement', 'webkitCancelFullScreen', 'webkitfullscreenchange', 'webkitfullscreenerror', ] // 省略一大堆 ] as any

再看useFullscreen方法:

export function useFullscreen( target?: MaybeElementRef, options: UseFullscreenOptions = {}, ) { const { document = defaultDocument, autoExit = false } = options // 获取目标元素 const targetRef = target || document?.querySelector('html') // isFullscreen根据目标是否全屏是响应式的 const isFullscreen = ref(false) // 是否支持不用响应式的,能支持就是能,不能就是不能 let isSupported = false // 取第一组全屏相关的方法 let map: FunctionMap = functionsMap[0] // document不存在肯定不支持 if (!document) { isSupported = false } else { // 检测functionsMap的所有元素(每一个元素都是一个数组,包含浏览器全屏相关的方法) for (const m of functionsMap) { // document 上存在退出全屏的方法 if (m[1] in document) { // 哪一种浏览器支持则使用对应那组方法 map = m // 支持后即可退出循环检查 isSupported = true break } } } // 解构出要使用的方法(REQUEST:请求全屏方法 EXIT:退出全屏 ELEMENT:当前全屏元素 EVENT:全屏change事件) const [REQUEST, EXIT, ELEMENT,, EVENT] = map // 退出全屏方法 async function exit() { if (!isSupported) return if (document?.[ELEMENT]) await document[EXIT]() isFullscreen.value = false } // 进入全屏方法 async function enter() { if (!isSupported) return await exit() // 目标元素 const target = unrefElement(targetRef) if (target) { await target[REQUEST]() isFullscreen.value = true } } // 切换 async function toggle() { if (isFullscreen.value) await exit() else await enter() } if (document) { // 事件监听 useEventListener(document, EVENT, () => { isFullscreen.value = !!document?.[ELEMENT] }, false) } if (autoExit) // 自动退出 tryOnScopeDispose(exit) return { isSupported, isFullscreen, enter, exit, toggle, } }

useFullscreen是使用hook的形式对全屏API进行了封装,useFullscreen方法返回了isSupported和isFullscreen两个变量用于判断是否支持全屏和是否在全屏状态;enter、exit 和toggle方法用于进入、退出和切换全屏。

4.总结

本文介绍了浏览器原生的全屏API, 然后介绍了使用较多的screenfull, 最后介绍了vueuse 提供的useFullscreen。screenfull和useFullscreen在本质上都是对浏览器原生API的封装。在实际项目中该如何选择呢? 欢迎您留言讨论~



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3