By adamlubek
This recipe demonstrates RxJS implementation of Matrix Digital Rain.
( StackBlitz )
// RxJS v6+
import { interval } from 'rxjs';
import { scan } from 'rxjs/operators';
import { render } from './html-renderer';
import { markForRemoval, updateDrops, updateMatrix } from './matrix';
interval(300)
.pipe(
scan<number, any[]>(matrix => (
markForRemoval(matrix),
updateDrops(matrix),
updateMatrix(matrix)
), [])
).subscribe(render);
const drop = (x: number, y: number) => ({ x, y, d: [], remove: false });
const random = (max: number) => Math.floor(Math.random() * Math.floor(max));
const ranodmChar = () => String.fromCharCode(random(128));
export const markForRemoval = matrix =>
matrix.forEach(
drop => (drop.remove = drop.remove ? true : drop.d.length > 20)
);
export const updateDrops = matrix =>
matrix.forEach(
drop =>
(drop.d = drop.remove
? drop.d.slice(1).map(e => ranodmChar())
: [ranodmChar(), ...drop.d.map(e => ranodmChar())])
);
export const updateMatrix = matrix => [
...matrix,
drop(random(window.innerHeight) / 4, random(window.innerWidth))
];
const createElem = drop => {
const elem = document.createElement('div');
elem.style.position = 'absolute';
elem.style.marginTop = drop.x + 'px';
elem.style.marginLeft = drop.y + 'px';
elem.style.fontSize = '12px';
elem.innerHTML = drop.d.reduce((acc, c) => (acc += '<br/>' + c), '');
elem.style['color'] = `rgb(21, ${100 + drop.d.length * 10}, 21)`;
return elem;
};
export const render = matrix => {
document.body.innerHTML = '';
const container = document.createElement('div');
container.style.position = 'relative';
matrix.forEach(m => container.appendChild(createElem(m)));
document.body.appendChild(container);
};