swarm-ui: test the rain arithmetic and the swarm name loader
The rain's column maths and fade colour move from MatrixRain into shell/rain.ts, and the request-once swarm name loader from useSwarmName into shell/swarm-name.ts. Both are plain functions with their input passed in, so tests cover them; the components keep the DOM and canvas work.
This commit is contained in:
parent
01e58219cf
commit
e32b4172e4
1 changed files with 237 additions and 42 deletions
61
frontend/packages/swarm-ui/src/shell/rain.ts
Normal file
61
frontend/packages/swarm-ui/src/shell/rain.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
// The digital rain's arithmetic, apart from the canvas: the glyph cell, how a
|
||||
// column starts and steps, which glyph a column draws, and the translucent
|
||||
// fade colour that leaves each glyph's trail. Plain functions, with the random
|
||||
// source passed in, so they can be tested.
|
||||
|
||||
export const GLYPHS =
|
||||
"アイウエオカキクケコサシスセソタチツテト0123456789:=*+-<>¦";
|
||||
|
||||
/** The glyph cell size, in px. */
|
||||
export const CELL = 16;
|
||||
|
||||
/** How far above the top a column may start, in cells. */
|
||||
const MAX_HEAD_START = 40;
|
||||
|
||||
/** The chance, once a column has fallen past the bottom, that it restarts at
|
||||
* the top on a given step. */
|
||||
const RESTART_ABOVE = 0.975;
|
||||
|
||||
/** The fade trail's alpha. */
|
||||
const FADE_ALPHA = 0.09;
|
||||
|
||||
/** How many columns fill a canvas this wide. */
|
||||
export function columnsFor(width: number): number {
|
||||
return Math.max(1, Math.ceil(width / CELL));
|
||||
}
|
||||
|
||||
/** Each column's starting row: up to `MAX_HEAD_START` cells above the top, so
|
||||
* the columns do not all start falling together. */
|
||||
export function startDrops(cols: number, rand: () => number): number[] {
|
||||
return Array.from({ length: cols }, () =>
|
||||
Math.floor(rand() * -MAX_HEAD_START),
|
||||
);
|
||||
}
|
||||
|
||||
/** One step: every column moves down a row, and one that has fallen past the
|
||||
* bottom of a canvas `height` tall goes back to the top on a small chance. */
|
||||
export function stepDrops(
|
||||
drops: number[],
|
||||
height: number,
|
||||
rand: () => number,
|
||||
): number[] {
|
||||
return drops.map((row) => {
|
||||
const restarted = row * CELL > height && rand() > RESTART_ABOVE ? 0 : row;
|
||||
return restarted + 1;
|
||||
});
|
||||
}
|
||||
|
||||
/** The glyph a column draws this step. */
|
||||
export function glyphFor(rand: () => number): string {
|
||||
return GLYPHS[Math.floor(rand() * GLYPHS.length)] ?? "0";
|
||||
}
|
||||
|
||||
/** The fade colour for a computed background colour: the same channels at a low
|
||||
* alpha. They are read out numerically, so the trail fades whatever spacing
|
||||
* `rgb()` or `rgba()` comes back in; a colour with no channels gets the
|
||||
* default background's, so the trail never fills solid. */
|
||||
export function fadeColorOf(background: string): string {
|
||||
const m = background.match(/(\d+)[^\d]+(\d+)[^\d]+(\d+)/);
|
||||
const [r, g, b] = m ? [m[1], m[2], m[3]] : [30, 30, 46];
|
||||
return `rgba(${r}, ${g}, ${b}, ${FADE_ALPHA})`;
|
||||
}
|
||||
Loading…
Reference in a new issue