Created
July 12, 2019 01:34
-
-
Save petermikitsh/8b327da04b5b51eb9cd45a074f132ec4 to your computer and use it in GitHub Desktop.
Lag Radar
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
( | |
function() { | |
const lagRadar = ( config = {} ) => { | |
const { | |
frames = 50, | |
speed = 0.0017, | |
size = 300, | |
inset = 3, | |
parent = document.body, | |
} = config; | |
const svgns = 'http://www.w3.org/2000/svg'; | |
const styles = document.createTextNode(` | |
.lagRadar { | |
position: fixed; | |
z-index: 9999999; | |
top: 0; | |
right: 0; | |
} | |
.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(); | |
} | |
}; | |
lagRadar({ | |
frames: 50, | |
speed: 0.0017, | |
size: 300, | |
inset: 3, | |
parent: document.body, | |
}); | |
} | |
)(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment