90 lines
2.4 KiB
TypeScript
90 lines
2.4 KiB
TypeScript
// Bühne für Trailer und Galerie (scripts/capture/trailer.mjs steuert sie über window.stage).
|
|
import './stage.css'
|
|
|
|
const $ = <T extends HTMLElement>(id: string) =>
|
|
document.getElementById(id) as T
|
|
const text = $('text')
|
|
const title = $('title')
|
|
const sub = $('sub')
|
|
const foot = $('foot')
|
|
const finger = $('finger')
|
|
const splash = $<HTMLIFrameElement>('splash')
|
|
const game = $<HTMLIFrameElement>('game')
|
|
const clip = $<HTMLVideoElement>('clip')
|
|
const post = $('post')
|
|
|
|
const sleep = (ms: number) => new Promise(r => setTimeout(r, ms))
|
|
|
|
/** Handy so groß wie möglich (88 % der Höhe) */
|
|
function fit(): void {
|
|
document.documentElement.style.setProperty(
|
|
'--s',
|
|
String((innerHeight * 0.88) / 840),
|
|
)
|
|
}
|
|
fit()
|
|
addEventListener('resize', fit)
|
|
|
|
function load(frame: HTMLIFrameElement, src: string): Promise<void> {
|
|
return new Promise(resolve => {
|
|
frame.addEventListener('load', () => resolve(), {once: true})
|
|
frame.src = src
|
|
})
|
|
}
|
|
|
|
declare global {
|
|
interface Window {
|
|
stage: typeof stage
|
|
}
|
|
}
|
|
|
|
const stage = {
|
|
async caption(
|
|
t: string,
|
|
s = '',
|
|
f = '',
|
|
opts: {logo?: boolean; instant?: boolean} = {},
|
|
) {
|
|
if (!opts.instant && title.textContent) {
|
|
text.classList.add('fade')
|
|
await sleep(250)
|
|
}
|
|
title.textContent = t
|
|
title.classList.toggle('logo', Boolean(opts.logo))
|
|
sub.textContent = s
|
|
foot.textContent = f
|
|
text.classList.remove('fade')
|
|
},
|
|
/** Was das Handy zeigt: Post im Feed, Spiel (Vollbild) oder eine eigene Aufnahme */
|
|
async show(mode: 'post' | 'game' | 'clip', src?: string) {
|
|
if (mode === 'post' && src) await load(splash, src)
|
|
if (mode === 'game' && src) await load(game, src)
|
|
if (mode === 'clip' && src) {
|
|
clip.src = src
|
|
await clip.play()
|
|
}
|
|
for (const [el, m] of [
|
|
[post, 'post'],
|
|
[game, 'game'],
|
|
[clip, 'clip'],
|
|
] as const)
|
|
el.classList.toggle('on', m === mode)
|
|
document.body.classList.toggle('post-mode', mode === 'post')
|
|
// Schriften im Spiel abwarten
|
|
await (mode === 'post' ? splash : game).contentDocument?.fonts.ready
|
|
},
|
|
clipDuration: () => clip.duration,
|
|
finger(x: number | null, y = 0) {
|
|
finger.classList.toggle('on', x !== null)
|
|
if (x !== null) {
|
|
finger.style.left = `${x}px`
|
|
finger.style.top = `${y}px`
|
|
}
|
|
},
|
|
press() {
|
|
finger.classList.remove('press')
|
|
void finger.offsetWidth
|
|
finger.classList.add('press')
|
|
},
|
|
}
|
|
window.stage = stage
|