Spaces:
Running
Running
| /** | |
| * WORKAROUND:CSS 伪全屏(fixed + 锁 body 滚动) | |
| * | |
| * 不参与 Fullscreen API。供「原生 `requestFullscreen` 不可用或拒绝」时降级使用; | |
| * 业务层应始终先尝试标准 API,再把本模块当作兜底(见 `genAttributeDagFullscreenWorkaround.ts`)。 | |
| * | |
| * 样式类名 {@link CSS_PSEUDO_FULLSCREEN_TARGET_CLASS} 须与页面 SCSS 一致。 | |
| */ | |
| /** 须与 gen_attribute.scss 中 WORKAROUND 段落的选择器一致 */ | |
| export const CSS_PSEUDO_FULLSCREEN_TARGET_CLASS = 'css-pseudo-fullscreen-target'; | |
| const BODY_LOCK_CLASS = 'css-pseudo-fullscreen-body-lock'; | |
| /** 伪全屏进/出时派发(`fullscreenchange` 不会为此触发) */ | |
| export const CSS_PSEUDO_FULLSCREEN_CHANGE_EVENT = 'css-pseudo-fullscreen-change'; | |
| let activeTarget: HTMLElement | null = null; | |
| let escapeListener: ((e: KeyboardEvent) => void) | null = null; | |
| function teardownEscape(): void { | |
| if (escapeListener) { | |
| document.removeEventListener('keydown', escapeListener); | |
| escapeListener = null; | |
| } | |
| } | |
| function notifyChange(): void { | |
| document.dispatchEvent(new CustomEvent(CSS_PSEUDO_FULLSCREEN_CHANGE_EVENT)); | |
| } | |
| export function cssPseudoFullscreenIsActive(el?: HTMLElement): boolean { | |
| if (!activeTarget) return false; | |
| return el === undefined ? true : activeTarget === el; | |
| } | |
| export function cssPseudoFullscreenEnter(el: HTMLElement): void { | |
| if (activeTarget === el) return; | |
| if (activeTarget && activeTarget !== el) cssPseudoFullscreenExit(); | |
| activeTarget = el; | |
| activeTarget.classList.add(CSS_PSEUDO_FULLSCREEN_TARGET_CLASS); | |
| document.body.classList.add(BODY_LOCK_CLASS); | |
| teardownEscape(); | |
| // 原生全屏时浏览器自己处理 Escape;伪全屏不走 Fullscreen API,须自行监听。 | |
| escapeListener = (e: KeyboardEvent): void => { | |
| if (e.key === 'Escape') { | |
| cssPseudoFullscreenExit(); | |
| } | |
| }; | |
| document.addEventListener('keydown', escapeListener); | |
| notifyChange(); | |
| } | |
| export function cssPseudoFullscreenExit(el?: HTMLElement): void { | |
| if (!activeTarget) return; | |
| if (el !== undefined && activeTarget !== el) return; | |
| activeTarget.classList.remove(CSS_PSEUDO_FULLSCREEN_TARGET_CLASS); | |
| document.body.classList.remove(BODY_LOCK_CLASS); | |
| activeTarget = null; | |
| teardownEscape(); | |
| notifyChange(); | |
| } | |