Last active
March 15, 2021 13:38
-
-
Save mscalora/072cc6ece562107907a4d151b1d70bac to your computer and use it in GitHub Desktop.
Perfect JS Counter
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> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Counter</title> | |
<style> | |
html { | |
height: 100%; | |
margin: 0; | |
padding: 0; | |
background: black; | |
color: white; | |
} | |
body { | |
min-height: 100vh; | |
margin: 0; | |
padding: 0; | |
display: grid; | |
place-items: center; | |
text-align: center; | |
} | |
#container { | |
border: 2px solid white; | |
padding: 1em 2em; | |
} | |
button { | |
position: fixed; | |
bottom: 4px; | |
right: 4px; | |
} | |
</style> | |
</head> | |
<body> | |
<div> | |
<div id="container">0</div> | |
<div><a href="https://www.youtube.com/watch?v=MCi6AZMkxcU" target="_blank">video</a></div> | |
</div> | |
<button id="stop" type="button">stop</button> | |
<script> | |
function animationInterval(ms, signal, callback) { | |
// Prefer currentTime, as it'll better sync animations queued in the | |
// same frame, but if it isn't supported, performance.now() is fine. | |
const start = document.timeline ? document.timeline.currentTime : performance.now(); | |
function frame(time) { | |
if (signal.aborted) return; | |
callback(time); | |
scheduleFrame(time); | |
} | |
function scheduleFrame(time) { | |
const elapsed = time - start; | |
const roundedElapsed = Math.round(elapsed / ms) * ms; | |
const targetNext = start + roundedElapsed + ms; | |
const delay = targetNext - performance.now(); | |
setTimeout(() => requestAnimationFrame(frame), delay); | |
} | |
scheduleFrame(start); | |
} | |
const controller = new AbortController(); | |
animationInterval(1000, controller.signal, time => { | |
let container = document.getElementById('container'); | |
if (container) { | |
container.innerHTML = Math.round(time/1000).toString(); | |
} | |
}); | |
let stopper = document.getElementById('stop'); | |
stopper.addEventListener('click', () => {controller.abort(); stopper.style.display = 'none';}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment