Created
April 23, 2023 19:56
-
-
Save fabiospampinato/8739843e34f43757989197337e93dd51 to your computer and use it in GitHub Desktop.
My lag bar implementation for Voby
This file contains hidden or 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
/* IMPORT */ | |
import {$, $$, useEffect, useInterval} from 'voby'; | |
/* STYLE */ | |
css` | |
:root { | |
--lag-bar-color-bg: var(--color-black-bg); | |
} | |
.ui-lag-bar { | |
position: relative; | |
display: flex; | |
overflow: hidden; | |
border-radius: var(--border-radius-smooth); | |
background-color: var(--lag-bar-color-bg); | |
/* FLOATING */ | |
&.floating { | |
position: absolute; | |
top: var(--gutter-100); | |
left: 50%; | |
transform: translateX(-50%); | |
box-shadow: var(--elevation-8); | |
z-index: var(--layer-8); | |
} | |
} | |
`; | |
/* TYPES */ | |
type $<T> = T | (() => T); | |
type Props = { | |
floating?: $<boolean>, | |
height?: $<number>, | |
interval?: $<number>, | |
width?: $<number> | |
}; | |
/* HELPERS */ | |
const sigmoid = ( value: number ): number => { | |
return 1 / ( 1 + Math.exp ( -value ) ); | |
}; | |
const useLag = ( interval: $<number>, callback: ( elapsed: number ) => void ): void => { | |
let start = performance.now (); | |
useInterval ( () => { | |
const end = performance.now (); | |
const elapsed = ( end - start ); | |
start = end; | |
callback ( elapsed ); | |
}, interval ); | |
}; | |
/* MAIN */ | |
const LagBar = ( { floating, height = 12, interval = 8, width = 256 }: Props ): JSX.Element => { | |
let ref = $<HTMLCanvasElement>(); | |
let ctx: CanvasRenderingContext2D | undefined | null; | |
let x = 0; | |
useEffect ( () => { | |
ctx = ref ()?.getContext ( '2d' ); | |
}); | |
useLag ( interval, elapsed => { | |
const h = $$(height); | |
const i = $$(interval); | |
const w = $$(width); | |
if ( !ctx ) return; | |
const percentage = sigmoid ( ( Math.min ( 1, elapsed / ( i * 10 ) ) - 0.5 ) * 5 ); | |
const green = Math.round ( 255 * ( 1 - percentage ) ).toString ( 16 ).padStart ( 2, '0' ); | |
const red = Math.round ( 255 * percentage ).toString ( 16 ).padStart ( 2, '0' ); | |
const color = `#${red}${green}00`; | |
const cursorSize = 4; | |
const elapsedSize = Math.round ( elapsed / i ); | |
const elapsedSizeChunk1 = Math.min ( w - x, elapsedSize ); | |
const elapsedSizeChunk2 = ( elapsedSize - elapsedSizeChunk1 ); | |
ctx.fillStyle = color; | |
ctx.fillRect ( x, 0, elapsedSizeChunk1, h ); | |
x = ( x + elapsedSizeChunk1 ) % w; | |
ctx.fillStyle = color; | |
ctx.fillRect ( x, 0, elapsedSizeChunk2, h ); | |
x = ( x + elapsedSizeChunk2 ) % w; | |
ctx.fillStyle = '#ffffffff'; | |
ctx.fillRect ( x, 0, cursorSize, h ); | |
}); | |
return ( | |
<div use:ui="lag-bar" class={{ floating }} style={{ width, height }}> | |
<canvas ref={ref} width={width} height={height} /> | |
</div> | |
); | |
}; | |
/* EXPORT */ | |
export default LagBar; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment