By adamlubek
This recipe shows usage of time interval operator in a simple game
( StackBlitz )
// RxJS v6+
import { fromEvent, TimeInterval } from 'rxjs';
import { timeInterval, takeWhile, scan, tap, repeat, finalize } from 'rxjs/operators';
import { render, clear } from './html-renderer';
interface State {
score: number;
interval: number;
threshold: number;
}
fromEvent(document, 'mousedown').pipe(
timeInterval(),
scan<TimeInterval<Event>, State>((state, timeInterval) => ({
score: state.score + 1,
interval: timeInterval.interval,
threshold: state.threshold - 2
}), { score: 0, interval: 0, threshold: 300 }),
takeWhile((state: State) => state.interval < state.threshold),
tap((state: State) => render(state.score, Math.floor(state.score / 10))),
finalize(clear),
repeat()
).subscribe();
const texts = {
0: 'click, click',
1: 'keep clicking',
2: 'wow',
3: 'not tired yet?!',
4: 'click master!',
5: 'inhuman!!!',
6: 'ininhuman!!!'
};
const text = (score: number, level: number) => `${texts[level]} \n ${score}`;
export const render = (score: number, level: number) => {
const id = 'level' + level;
const element = document.getElementById(id);
const innerText = text(score, level);
if (element) {
element.innerText = innerText;
} else {
const elem = document.createElement('div');
elem.id = id;
elem.style.zIndex = `${level}`;
elem.style.position = 'absolute';
elem.style.height = '150px';
elem.style.width = '150px';
elem.style.borderRadius = '10px';
const position = level * 20;
elem.style.top = position + 'px';
elem.style.left = position + 'px';
const col = 100 + position;
elem.style.background = `rgb(0,${col},0)`;
elem.style.color = 'white';
elem.innerText = innerText;
elem.style.textAlign = 'center';
elem.style.verticalAlign = 'middle';
elem.style.lineHeight = '90px';
document.body.appendChild(elem);
}
};
export const clear = () => (document.body.innerText = '');
<div>How fast can you click?!</div>