|
76 | 76 | } |
77 | 77 |
|
78 | 78 | function show(to, from) { |
79 | | - const playPromise = playVideo(to); |
| 79 | + playVideo(to); |
80 | 80 | requestAnimationFrame(() => { |
81 | 81 | to.style.opacity = '1'; |
82 | 82 | if (from) { |
|
85 | 85 | }, { once: true }); |
86 | 86 | } |
87 | 87 | }); |
88 | | - return playPromise; |
| 88 | + } |
| 89 | + |
| 90 | + function holdPhase3EndFrame(from) { |
| 91 | + phase = 'awaiting-entry'; |
| 92 | + phase3ReadyToEnter = true; |
| 93 | + hidePrompt(); |
| 94 | + requestAnimationFrame(() => { |
| 95 | + v3.style.opacity = '1'; |
| 96 | + if (from) { |
| 97 | + v3.addEventListener('transitionend', () => { |
| 98 | + from.style.opacity = '0'; |
| 99 | + }, { once: true }); |
| 100 | + } |
| 101 | + }); |
| 102 | + |
| 103 | + const seekToEndFrame = () => { |
| 104 | + const safeDuration = Number.isFinite(v3.duration) ? v3.duration : 0; |
| 105 | + const endFrameTime = safeDuration > 0.08 ? safeDuration - 0.05 : Math.max(safeDuration, 0); |
| 106 | + v3.currentTime = endFrameTime; |
| 107 | + v3.pause(); |
| 108 | + }; |
| 109 | + |
| 110 | + if (v3.readyState >= HTMLMediaElement.HAVE_METADATA) { |
| 111 | + seekToEndFrame(); |
| 112 | + } else { |
| 113 | + v3.addEventListener('loadedmetadata', seekToEndFrame, { once: true }); |
| 114 | + v3.load(); |
| 115 | + } |
89 | 116 | } |
90 | 117 |
|
91 | 118 | function goToPhase3() { |
92 | | - if (phase === 'phase3' || phase === 'done') return; |
| 119 | + if (phase === 'phase3' || phase === 'awaiting-entry' || phase === 'done') return; |
93 | 120 | const from = phase === 'loop' ? v2 : v1; |
94 | | - phase = 'phase3'; |
95 | 121 | phase3ReadyToEnter = false; |
96 | 122 | v2.loop = false; |
97 | 123 | v2.pause(); |
98 | | - hidePrompt(); |
99 | | - const playPromise = show(v3, from); |
100 | | - if (playPromise && typeof playPromise.catch === 'function') { |
101 | | - playPromise.catch(() => { |
102 | | - phase = 'awaiting-entry'; |
103 | | - phase3ReadyToEnter = true; |
104 | | - setPrompt('PRESS SPACE / TAP TO ENTER'); |
105 | | - }); |
106 | | - } |
| 124 | + holdPhase3EndFrame(from); |
107 | 125 | } |
108 | 126 |
|
109 | 127 | function enterWebsite() { |
|
213 | 231 | v1.addEventListener('canplay', () => playVideo(v1), { once: true }); |
214 | 232 | } |
215 | 233 |
|
216 | | - // phase3 - wait for explicit enter input |
217 | | - v3.addEventListener('ended', () => { |
218 | | - if (cutsceneDone) return; |
219 | | - phase = 'awaiting-entry'; |
220 | | - phase3ReadyToEnter = true; |
221 | | - setPrompt('PRESS SPACE / TAP TO ENTER'); |
222 | | - }, { once: true }); |
223 | | - |
224 | 234 | }); |
225 | 235 | })(); |
0 commit comments