EPIC: The Musical
+The voyage home, charted
+Sail past every song. The longer the crossing, the more years pass in the story.
+ +diff --git a/src/mockups/07-sea-voyage/index.html b/src/mockups/07-sea-voyage/index.html index b7a3229..a5dd6ea 100644 --- a/src/mockups/07-sea-voyage/index.html +++ b/src/mockups/07-sea-voyage/index.html @@ -8,7 +8,24 @@
- +EPIC: The Musical
+Sail past every song. The longer the crossing, the more years pass in the story.
+ +stub
`; +const credits = mountCredits(); +const $ = (id: string) => document.getElementById(id)!; +const sea = $("sea"); +const pennants = $("pennants"); +const logline = $("logline"); +const drawer = $("drawer"); +const fallback = $("fallback"); +const nowEl = $("now"); + +const params = new URLSearchParams(location.search); +const reducedMq = window.matchMedia("(prefers-reduced-motion: reduce)"); +const narrowMq = window.matchMedia("(max-width: 760px)"); +const SAIL_SPEED = 0.32; // sea lengths per second + +const esc = (s: string) => s.replace(/[&<>"']/g, (ch) => `${ch.charCodeAt(0)};`); +const motifById = (id: string) => motifs.find((m) => m.id === id); +const stopById = (id: string) => stops.find((s) => s.song.id === id); +const pct = (d: number) => `${(toUnit(d) * 100).toFixed(3)}%`; + +let scene: VoyageScene | null = null; +let target = routeMin + 0.15; +let current = target; +let sailing = !reducedMq.matches; +let motifId: string | null = null; +let openId: string | null = null; +let lastNear: string | null = null; +let raf = 0; +let last = 0; +let returnFocus: HTMLElement | null = null; + +/* ---------- credits always sit above everything; panels stop above them ---------- */ + +const footRo = new ResizeObserver(() => { + document.documentElement.style.setProperty("--foot-h", `${credits.offsetHeight}px`); +}); +footRo.observe(credits); + +/* ---------- motif pennants ---------- */ + +function renderPennants() { + const group = (kind: Motif["kind"], title: string) => ` +${title}
+Pick a motif to light every waypoint and part where it returns.
`; + pennants.addEventListener("click", (e) => { + const btn = (e.target as HTMLElement).closestScroll, drag the sea or press ← → to sail. Each year in the story is a long crossing; songs in the same year sit one short hop apart.
+Waypoint ${song.track} of ${songs.length}, ${esc(saga.name)}
+Sung by ${esc(p.singers.join(" and "))}
${esc(l)}
`).join("")}${esc(f)}
`).join("")} +This view paints a 3D sea with WebGL, which this browser has switched off or doesn't support. Turn on hardware acceleration, or try another browser, to sail it.
+Meanwhile the voyage log still works. Pick a waypoint below to read its song.
+