Created
October 10, 2024 23:58
-
-
Save hajimehoshi/6d4994cee36221ab8dbdb04a363cf1aa to your computer and use it in GitHub Desktop.
Loading screen
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<style> | |
body { | |
background-color: black; | |
margin: 0; | |
padding: 0; | |
overflow: hidden; | |
font-family: sans-serif; | |
color: white; | |
font-size: 30px; | |
} | |
#loading { | |
width: 100dvw; | |
height: 100dvh; | |
display: flex; | |
flex-direction: column; | |
justify-content: space-evenly; | |
align-items: center; | |
text-align: center; | |
} | |
#progress { | |
display: flex; | |
flex-direction: column; | |
align-items: end; | |
width: 80%; | |
} | |
#progress > span { | |
text-align: end; | |
} | |
#progress > progress { | |
width: 100%; | |
height: 40px; | |
} | |
</style> | |
<div id="loading"><div>DOWNLOADING...</div><div id="progress"><span></span><progress></progress></div></div> | |
<script src="wasm_exec.js"></script> | |
<script> | |
window.addEventListener('DOMContentLoaded', async () => { | |
const loading = document.getElementById('loading'); | |
const observer = new MutationObserver((mutationList) => { | |
for (let mutation of mutationList) { | |
if (mutation.type !== 'childList') { | |
continue; | |
} | |
for (const node of mutation.addedNodes) { | |
if (node.tagName !== 'CANVAS') { | |
continue; | |
} | |
node.focus(); | |
loading.remove(); | |
observer.disconnect(); | |
return; | |
} | |
} | |
}); | |
observer.observe(document.body, {childList: true, subtree: true}); | |
// Create a stream with progress. | |
const response = await fetch('game.wasm'); | |
// Unfortunately Content-Length might not be available on some servers. | |
// Hardcode the value. | |
const contentLength = 1234567890; // The size of game.wasm in bytes. | |
let loaded = 0; | |
const progress = document.getElementById('progress'); | |
const progressBar = progress.querySelector('progress'); | |
progressBar.max = contentLength; | |
const progressText = progress.querySelector('span'); | |
const responseWithProgress = new Response(new ReadableStream({ | |
async start(controller) { | |
const reader = response.body.getReader(); | |
for (;;) { | |
const {done, value} = await reader.read(); | |
if (done) { | |
break; | |
} | |
loaded += value.byteLength; | |
const rate = loaded / contentLength; | |
progressText.textContent = `${(rate * 100).toFixed(2)}%`; | |
progressBar.value = loaded; | |
controller.enqueue(value); | |
} | |
controller.close(); | |
}, | |
}, { | |
'status': response.status, | |
'statusText': response.statusText, | |
})); | |
for (const pair of response.headers.entries()) { | |
responseWithProgress.headers.set(pair[0], pair[1]); | |
} | |
const go = new Go(); | |
const result = await WebAssembly.instantiateStreaming(responseWithProgress, go.importObject) | |
go.run(result.instance); | |
}) | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment