- 前端
【免费下载链接】screenfull
Simple wrapper for cross-browser usage of the JavaScript Fullscreen API
本文围绕开源仓库 screenfull 的官方文档展开,系统讲解这一「简单包装器(Simple wrapper)」如何封装浏览器原生 Fullscreen API、抹平各厂商前缀差异,并给出完整的安装、API 参考、实战示例与源码级原理剖析。读完本文,你将能够用统一、极简的 API 在任意支持的浏览器中实现页面或指定元素的全屏切换,并正确处理移动端、iframe、jQuery 与 Angular 等场景。
screenfull 是一个「功能已完整、不再接受新特性」的成熟库(readme.md),其核心价值在于:用 0.7 kB(gzipped)的体积,把标准、WebKit、旧 WebKit、Mozilla、Microsoft 五套 Fullscreen API 前缀差异全部封装掉,让你无需关心webkitRequestFullscreen还是mozRequestFullScreen,统一调用screenfull.request()即可。
一、安装与版本选择
screenfull 仅依赖浏览器原生 Fullscreen API,没有任何运行时依赖,安装极其简单:
npm install screenfull安装后体积约0.7 kB(gzipped)(readme.md)。
关于 ESM 的重要说明
当前版本的 screenfull 是纯 ESM(ECMAScript Module)包(package.json 中"type": "module"且"exports": "./index.js"),这意味着:
- 你可以直接使用
import screenfull from 'screenfull'引入; - 如果项目处于 CommonJS 环境,或需要在不经过转译(transpilation)的情况下支持旧浏览器,官方明确建议改用 5.2.0 版本(readme.md);
- 从 package.json 的
engines字段可以看到,Node.js 环境要求^14.13.1 || >=16.0.0。
基本引入方式
import screenfull from 'screenfull'; if (screenfull.isEnabled) { screenfull.request(); }二、为什么需要 screenfull:与原生 API 的对比
这是理解 screenfull 价值的最好入口。官方文档(readme.md)给出了同一需求的两版代码对比。
使用 screenfull
import screenfull from 'screenfull'; if (screenfull.isEnabled) { screenfull.request(); }使用原生 JavaScript
document.fullscreenEnabled = document.fullscreenEnabled || document.mozFullScreenEnabled || document.documentElement.webkitRequestFullScreen; function requestFullscreen(element) { if (element.requestFullscreen) { element.requestFullscreen(); } else if (element.mozRequestFullScreen) { element.mozRequestFullScreen(); } else if (element.webkitRequestFullScreen) { element.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT); } } if (document.fullscreenEnabled) { requestFullscreen(document.documentElement); } // This is not even entirely comprehensive. There's more.正如文档所注:原生方案「甚至还不全面,还有更多细节」。浏览器厂商各自实现过带前缀的 API,属性名、方法名、事件名、甚至exit在不同浏览器中叫exitFullscreen、mozCancelFullScreen、webkitCancelFullScreen……而 screenfull 在底层将这些差异集中收纳进一张「方法映射表」,对外暴露一套统一 API。
三、浏览器支持情况
- 所有支持 Fullscreen API 的现代浏览器均可使用(文档引用了 caniuse 的 fullscreen 兼容性数据);
- 特别说明:Safari 在桌面端和 iPad 上受支持,但在 iPhone 上不受支持。这是浏览器本身的限制,不是 screenfull 的缺陷(readme.md)。
iframe 中的使用前提
如果你的页面位于<iframe>内,要进入全屏必须给 iframe 标签加上allowfullscreen属性(以及兼容旧浏览器的webkitallowfullscreen和mozallowfullscreen)。这一点同时影响.request()与.isEnabled两个 API 的表现,下文会再次提到。
四、完整 API 参考
screenfull 对外暴露的全部 API 均可在 index.d.ts 的类型声明中看到,其方法签名与 index.js 的实现一一对应。
.request(element, options?)
让指定元素进入全屏。
- element:默认是
<html>文档根元素;如果传入的是当前全屏元素的子元素,会切换到该元素;非子元素则不会切换; - options:标准
FullscreenOptions对象,即原生 Fullscreen API 的选项; - 返回:一个 Promise,在元素进入全屏后 resolve。
import screenfull from 'screenfull'; document.getElementById('button').addEventListener('click', () => { if (screenfull.isEnabled) { screenfull.request(); } else { // 忽略或做其他处理 } });重要约束:浏览器只允许在用户手势(click、touch、key 等)发起的回调中进入全屏,request()必须由用户事件触发。
.exit()
退出全屏。
- 返回:一个 Promise,在元素退出全屏后 resolve。
await screenfull.exit();从源码(index.js)可以看到,exit()会先判断screenfull.isFullscreen,若当前不在全屏状态则立即 resolve,避免无意义的调用。
.toggle(element, options?)
如果当前不在全屏则请求进入,否则退出全屏。
- 参数与
.request()一致(DOM 元素 +FullscreenOptions); - 返回:一个 Promise,在元素进入/退出全屏后 resolve。
源码(index.js)的实现非常简洁,本质上是对上面两个方法的三元选择:
toggle(element, options) { return screenfull.isFullscreen ? screenfull.exit() : screenfull.request(element, options); },.on(event, function) 与 .off(event, function)
- 事件类型仅有两个:
'change' | 'error'(index.d.ts 中EventName类型):change:浏览器在全屏状态之间切换时触发;error:全屏操作发生错误时触发;
.on()注册监听器,.off()移除之前注册的监听器。
import screenfull from 'screenfull'; // 监听全屏状态变化 if (screenfull.isEnabled) { screenfull.on('change', () => { console.log('Am I fullscreen?', screenfull.isFullscreen ? 'Yes' : 'No'); }); } // 监听全屏错误 if (screenfull.isEnabled) { screenfull.on('error', event => { console.error('Failed to enable fullscreen', event); }); } // 移除监听器 screenfull.off('change', callback);从 index.js 可以看到.on/.off内部会根据eventNameMap把逻辑事件名映射到浏览器实际的前缀事件名,再调用document.addEventListener/removeEventListener的第三个参数为false(冒泡阶段)。
.onchange(function) 与 .onerror(function)
分别是.on('change', function)和.on('error', function)的简写别名,由 index.js 直接转发实现:
onchange(callback) { screenfull.on('change', callback); }, onerror(callback) { screenfull.on('error', callback); },.isFullscreen
布尔值,表示当前是否处于全屏状态。注意它是一个getter 属性(见 index.js),内部通过Boolean(document[nativeAPI.fullscreenElement])实时读取。
.element
返回当前处于全屏状态的元素;若不在全屏状态则返回undefined。同样由 getter 实现:document[nativeAPI.fullscreenElement] ?? undefined(index.js)。
.isEnabled
布尔值,表示当前是否被允许进入全屏。iframe 中需要allowfullscreen等属性才会为true。其 getter 为Boolean(document[nativeAPI.fullscreenEnabled]),注释特别说明「Coerce to boolean in case of old WebKit」,即对旧 WebKit 的非布尔返回值做强制布尔化处理(index.js)。
.raw
暴露内部实际使用的「带前缀的原始属性名」,共六项:requestFullscreen、exitFullscreen、fullscreenElement、fullscreenEnabled、fullscreenchange、fullscreenerror(index.js)。
在 index.d.ts 中对应RawEventNames类型,全部为readonly string。当你需要直接访问浏览器原生 API 时(比如做更底层的控制),可通过screenfull.raw拿到真正的属性名。
五、实战示例:从页面到元素的六种全屏场景
以下示例均来自官方文档(readme.md),可直接复制运行。
1. 全屏整个页面
默认即全屏<html>根元素:
import screenfull from 'screenfull'; document.getElementById('button').addEventListener('click', () => { if (screenfull.isEnabled) { screenfull.request(); } else { // Ignore or do something else } });2. 全屏指定元素
传入任意 DOM 元素:
import screenfull from 'screenfull'; const element = document.getElementById('target'); document.getElementById('button').addEventListener('click', () => { if (screenfull.isEnabled) { screenfull.request(element); } });3. 移动端隐藏导航 UI
通过FullscreenOptions的navigationUI选项控制移动端导航界面:
import screenfull from 'screenfull'; const element = document.getElementById('target'); document.getElementById('button').addEventListener('click', () => { if (screenfull.isEnabled) { screenfull.request(element, {navigationUI: 'hide'}); } });4. 用 jQuery 全屏一个元素
jQuery 集合需先取出原始 DOM 节点:
import screenfull from 'screenfull'; const element = $('#target')[0]; // Get DOM element from jQuery collection $('#button').on('click', () => { if (screenfull.isEnabled) { screenfull.request(element); } });5. 点击图片切换全屏(jQuery)
import screenfull from 'screenfull'; $('img').on('click', event => { if (screenfull.isEnabled) { screenfull.toggle(event.target); } });6. 监听全屏状态变化与错误
见上文.on('change')与.on('error')示例。官方演示页 index.html 给出了一个完整的联动示例:监听change事件后,根据screenfull.element实时刷新页面上「当前全屏元素」的显示文本:
function fullscreenchange() { const {element} = screenfull; // 更新状态文本... if (element) { $('#element').text(`Element: ${element.localName}${element.id ? `#${element.id}` : ''}`); } } screenfull.on('change', fullscreenchange);六、框架集成:Angular.js 与 Angular 2 指令封装
Angular.js(AngularJS 1.x)
官方文档推荐使用社区封装的 angular-screenfull 绑定,可以在模板中直接声明式使用:
<div ngsf-fullscreen> <p>This is a fullscreen element</p> <button ngsf-toggle-fullscreen>Toggle fullscreen</button> </div>Angular 2(现代 Angular)
可以直接用@Directive封装成自定义指令,把全屏逻辑收敛到指令内部:
import {Directive, HostListener} from '@angular/core'; import screenfull from 'screenfull'; @Directive({ selector: '[toggleFullscreen]' }) export class ToggleFullscreenDirective { @HostListener('click') onClick() { if (screenfull.isEnabled) { screenfull.toggle(); } } }<button toggleFullscreen>Toggle fullscreen<button>七、源码原理剖析:screenfull 如何抹平浏览器差异
1. 前缀探测:methodMap 与 nativeAPI
核心机制是 index.js 顶部的methodMap数组——按「标准 → 新 WebKit → 旧 WebKit → Mozilla → Microsoft」五个梯队组织六类 API 名称:
| 梯队 | 进入全屏 | 退出全屏 | 全屏元素 | 是否可用 | change 事件 | error 事件 |
|---|---|---|---|---|---|---|
| 标准 | requestFullscreen | exitFullscreen | fullscreenElement | fullscreenEnabled | fullscreenchange | fullscreenerror |
| 新 WebKit | webkitRequestFullscreen | webkitExitFullscreen | webkitFullscreenElement | webkitFullscreenEnabled | webkitfullscreenchange | webkitfullscreenerror |
| 旧 WebKit | webkitRequestFullScreen | webkitCancelFullScreen | webkitCurrentFullScreenElement | webkitCancelFullScreen | webkitfullscreenchange | webkitfullscreenerror |
| Mozilla | mozRequestFullScreen | mozCancelFullScreen | mozFullScreenElement | mozFullScreenEnabled | mozfullscreenchange | mozfullscreenerror |
| Microsoft | msRequestFullscreen | msExitFullscreen | msFullscreenElement | msFullscreenEnabled | MSFullscreenChange | MSFullscreenError |
然后通过nativeAPI立即执行检测(index.js):遍历methodMap,只要发现某个梯队的退出全屏方法存在于document上,就认定该浏览器使用这一套前缀,并把整套真实属性名映射到「标准名」上返回。因此无论底层叫什么,screenfull 对外永远统一。
2. Promise 化的事件驱动实现
.request()(index.js)没有直接依赖原生返回值,而是采用事件驱动 + Promise 包装策略:
- 先注册一次性的
change监听器onFullScreenEntered; - 调用
elementnativeAPI.requestFullscreen; - 如果原生方法返回的是 Promise(新标准浏览器),则通过
.then(onFullScreenEntered)收尾,.catch(reject)兜底错误。
.exit()(index.js)采用同样模式。这种双轨设计保证了:即便在不返回 Promise 的旧前缀实现上,也能通过change事件获得一致的 Promise 语义。
3. 优雅降级与 SSR 安全
- 如果
typeof document === 'undefined'(Node/SSR 环境),nativeAPI直接返回false(index.js); - 如果当前浏览器根本不支持 Fullscreen API,最终导出的
screenfull会被整体替换为{isEnabled: false}(index.js),任何调用都不会抛错,便于你按isEnabled做无全屏时的降级 UI。
4. 状态属性为何用 getter 实现
isFullscreen、element、isEnabled三个状态全部通过Object.defineProperties定义为getter 而非静态值(index.js),每次访问都实时读取document上的状态,从而保证change事件回调里拿到的永远是最新状态。
八、TypeScript 类型支持
screenfull 自带完整类型声明 index.d.ts,开箱即用:
EventName = 'change' | 'error':约束事件名;RawEventNames:raw属性对应的六项字符串类型;- 所有方法均标注返回类型,如
request(element?: Element, options?: FullscreenOptions): Promise<void>。
类型测试位于 index.test-d.ts,通过tsd断言了全部 API 的签名:request/toggle/exit返回Promise<void>,on/off/onchange/onerror的 handler 参数为Event,raw各字段均为string。项目质量检查脚本(package.json 的"test": "xo && tsd")同时运行xo(lint)与tsd(类型测试),从测试写法即可放心地把screenfull用在严格类型检查的项目中。
九、FAQ:全屏状态下如何跳转到新页面
问题:全屏时如何导航到新页面?
答案:出于安全原因,浏览器不支持在全屏状态下直接跳转页面。官方文档(readme.md)给出的变通方案是——创建一个铺满屏幕的无缝 iframe,在 iframe 内部加载新页面:
import screenfull from 'screenfull'; document.querySelector('#new-page-button').addEventListener(() => { const iframe = document.createElement('iframe') iframe.setAttribute('id', 'external-iframe'); iframe.setAttribute('src', 'https://new-page-website.com'); iframe.setAttribute('frameborder', 'no'); iframe.style.position = 'absolute'; iframe.style.top = '0'; iframe.style.right = '0'; iframe.style.bottom = '0'; iframe.style.left = '0'; iframe.style.width = '100%'; iframe.style.height = '100%'; document.body.prepend(iframe); document.body.style.overflow = 'hidden'; });演示页 index.html 中还在fullscreenchange回调里做了配套清理:当退出全屏(!screenfull.isFullscreen)时移除#external-iframe并恢复document.body.style.overflow = 'auto',避免残留元素遮挡页面。
十、使用注意事项与最佳实践
- 先判断再调用:所有全屏操作前都应检查
screenfull.isEnabled,这在 iframe、iPhone Safari 等受限场景下尤为重要; - 必须由用户手势触发:
request()需要在 click、touch、key 事件回调中调用,否则会被浏览器拒绝并触发error事件; - 及时清理监听器:使用
.on()注册后,记得在合适时机用.off()移除,避免内存泄漏和重复回调; - iframe 场景:给 iframe 添加
allowfullscreen(以及旧浏览器的webkitallowfullscreen、mozallowfullscreen)属性; - 版本选择:ESM 环境使用当前版本;CommonJS 或需兼容未转译旧浏览器时使用 5.2.0;
- 降级体验:
isEnabled === false时不要隐藏按钮,应改为提示「当前环境不支持全屏」或直接忽略操作。
延伸阅读
- 项目类型声明与实现:index.d.ts、index.js
- 类型测试:index.test-d.ts
- 官方演示页面(包含 Request / Exit / Toggle 按钮与图片全屏示例):index.html
- 许可证:MIT(license)
screenfull 的定位非常克制——它只做一件事(统一跨浏览器全屏 API)并且做到极致。理解了methodMap探测机制与 Promise 包装策略后,你不仅能熟练使用它,也能在遇到类似「前缀差异 API 统一封装」需求时,复用同样的设计思路。
- 前端
【免费下载链接】screenfull
Simple wrapper for cross-browser usage of the JavaScript Fullscreen API
相关推荐
大屏展示系统开发:screenfull多显示器全屏控制方案
大屏展示系统开发:screenfull多显示器全屏控制方案 在数据可视化和监控系统开发中,多显示器环境下的全屏控制一直是前端工程师面临的棘手问题。不同浏览器对全
前端Screenfull全屏API跨浏览器兼容解决方案
Screenfull全屏API跨浏览器兼容解决方案 在现代Web开发中,全屏体验已成为提升用户体验的重要一环。Screenfull作为JavaScript全屏A
前端vum框架性能优化终极指南:提升移动端应用加载速度的5个简单方法
vum框架性能优化终极指南:提升移动端应用加载速度的5个简单方法 在移动端开发中,性能优化是决定用户体验的关键因素。vum框架作为基于Vue.js的移动端UI框
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考