typescript 實現瀏覽器全屏
阿新 • • 發佈:2020-12-12
最近後臺專案需要一個"全屏"的按鈕, github了下, 發現都僅僅支援"開啟全屏", 而沒有"切換"/"監聽全屏狀態"等功能, 所以打算自己寫一個(主要程式碼量不大, 嘿嘿).
寫程式碼之前說說邏輯
所有現代瀏覽器(>IE11)都提供了"全屏"的api,只是不同瀏覽器有不同的api(基本就是字首不同), 所以我們要做的就是判斷瀏覽器, 然後執行正確的api.
- 判斷當前瀏覽器支援的字首, 比如"webkit".
- 根據字首得出我們需要的4個api的名字.
- 通過api實現"全屏"/"退出"/"切換"/"監聽".
程式碼
首先我發現ts自帶的宣告中, 對webkit或moz開頭的這種api並沒有宣告型別, 所以我們需要自己補充一下.
不然ts會提示找不到對應的方法.
知識點: 在自己的.d.ts檔案中可以對ts系統自帶的interface進行宣告合併(擴充套件).
// global.d.ts
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>;
}
提示:requestFullscreen(options?: FullscreenOptions): Promise<void>;可以在node_modules/typescript/lib/lib.dom.d.ts中找到.
資源搜尋網站大全 https://www.renrenfan.com.cn 廣州VI設計公司https://www.houdianzi.com
功能實現
功能其實很簡單, 我都寫了註釋, 就不過分解讀了, 好了看實現程式碼:
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, 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
}
}