Created
October 23, 2018 19:25
-
-
Save jstoppa/d2f09f54ae5f041ebc304775c094a4ec to your computer and use it in GitHub Desktop.
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> | |
<head> | |
<title>Lag Radar</title> | |
<style> | |
BODY { | |
color: white; | |
background: white; | |
font-family: Futura, "Trebuchet MS", sans-serif; | |
margin: 3em auto; | |
font-style: italic; | |
text-align: center; | |
} | |
#lagger { | |
padding: 20px 10px; | |
} | |
#lag { | |
width: 260px; | |
vertical-align: text-bottom; | |
} | |
#val { | |
display: inline-block; | |
text-align: right; | |
width: 3em; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="lagger"> | |
<!-- Induce Lag: | |
<input id="lag" type="range" min="0" max="1000" value="0"> | |
<span id="val">0</span>ms --> | |
</div> | |
<script type="module"> | |
/** | |
* lagRadar | |
* Licence: ISC copyright: @mobz 2018 | |
*/ | |
export default function lagRadar( config = {} ) { | |
const { | |
frames = 50, // number of frames to draw, more = worse performance | |
speed = 0.0017, // how fast the sweep moves (rads per ms) | |
size = 300, // outer frame px | |
inset = 3, // circle inset px | |
parent = document.body, // DOM node to attach to | |
} = config; | |
const svgns = 'http://www.w3.org/2000/svg'; | |
const styles = document.createTextNode(` | |
.lagRadar-sweep > * { | |
shape-rendering: crispEdges; | |
} | |
.lagRadar-face { | |
fill: transparent; | |
} | |
.lagRadar-hand { | |
stroke-width: 4px; | |
stroke-linecap: round; | |
} | |
`); | |
function $svg(tag, props = {}, children = []) { | |
const el = document.createElementNS(svgns, tag); | |
Object.keys(props).forEach( prop => el.setAttribute( prop, props[prop] ) ); | |
children.forEach( child => el.appendChild( child ) ); | |
return el; | |
} | |
const PI2 = Math.PI * 2; | |
const middle = size / 2; | |
const radius = middle - inset; | |
const $hand = $svg('path', { class: 'lagRadar-hand' }); | |
const $arcs = (new Array(frames)).fill('path').map(t => $svg(t)); | |
const $root = $svg('svg', { class: 'lagRadar', height: size, width: size }, [ | |
$svg('style', { type: 'text/css' }, [ styles ]), | |
$svg('g', { class: 'lagRadar-sweep' }, $arcs), | |
$hand, | |
$svg('circle', { class: 'lagRadar-face', cx: middle, cy: middle, r: radius }) | |
]); | |
parent.appendChild($root); | |
let frame; | |
let framePtr = 0; | |
let last = { | |
rotation: 0, | |
now: Date.now(), | |
tx: middle + radius, | |
ty: middle, | |
}; | |
const calcHue = (() => { | |
const max_hue = 120; | |
const max_ms = 1000; | |
const log_f = 10; | |
const mult = max_hue / Math.log(max_ms / log_f); | |
return function(ms_delta) { | |
return max_hue - Math.max(0, Math.min(mult * Math.log(ms_delta / log_f), max_hue ) ); | |
}; | |
})(); | |
function animate() { | |
const now = Date.now(); | |
const rdelta = Math.min(PI2 - speed, speed * (now - last.now)); | |
const rotation = (last.rotation + rdelta) % PI2; | |
const tx = middle + radius * Math.cos(rotation); | |
const ty = middle + radius * Math.sin(rotation); | |
const bigArc = rdelta < Math.PI ? '0' : '1'; | |
const path = `M${tx} ${ty}A${radius} ${radius} 0 ${bigArc} 0 ${last.tx} ${last.ty}L${middle} ${middle}`; | |
const hue = calcHue(rdelta/speed); | |
$arcs[framePtr % frames].setAttribute('d', path); | |
$arcs[framePtr % frames].setAttribute('fill', `hsl(${hue}, 80%, 40%)`); | |
$hand.setAttribute('d', `M${middle} ${middle}L${tx} ${ty}`); | |
$hand.setAttribute('stroke', `hsl(${hue}, 80%, 60%)`); | |
for (let i = 0; i < frames; i++) { | |
$arcs[(frames + framePtr - i) % frames].style.fillOpacity = 1 - (i/frames); | |
} | |
framePtr++; | |
last = { now, rotation, tx, ty }; | |
frame = window.requestAnimationFrame(animate); | |
} | |
animate(); | |
return function destroy() { | |
if(frame) { | |
window.cancelAnimationFrame(frame); | |
} | |
$root.remove(); | |
} | |
}; | |
const destroy = lagRadar(); | |
// document.body.addEventListener('click', destroy ); | |
(function lagMe() { | |
//let lag = document.getElementById('lag').value; | |
//document.getElementById('val').textContent = lag; | |
//const t1 = parseInt(lag, 10) + Date.now(); | |
//while( Date.now() < t1 ); | |
window.requestAnimationFrame(lagMe); | |
})(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment