How to detect konami code with Rx.js (reactive extensions for javascript)?
I want to start learning Rx.js and I'm looking for a cool example to start the ball rolling. How do I detect konami code with Rx.js?
I want to dete开发者_如何学Goct a sequence of key press events (up up down down left right left right B A) and display an image if this happens.
Here is my version:
<html>
<head>
<script type="text/javascript" src="jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="rx.js"></script>
<script type="text/javascript" src="rx.jQuery.js"></script>
</head>
<body>
<p id="result"></p>
<script type="text/javascript">
$(function() {
var konami = $(document).toObservable("keyup").Select(function(e) {
return e.keyCode
}).SkipWhile(function(k) {
return (k != 38)
}).BufferWithCount(
10
).Where(function(ks) {
return ks.length == 10 &&
ks[0] == 38 && ks[1] == 38 &&
ks[2] == 40 && ks[3] == 40 &&
ks[4] == 37 && ks[5] == 39 &&
ks[6] == 37 && ks[7] == 39 &&
ks[8] == 66 && ks[9] == 65
})
var konamisub = konami.Subscribe(function(e) {
$("#result").text("KONAMI!")
$("#result").fadeIn().fadeOut()
})
})
</script>
</body>
</html>
I convert the stream of keyup events into a stream of keycodes with the Select
, then ignoring keypresses until the user press up (keycode 38) with the SkipWhile
, then collecting 10 keystrokes with the BufferWithCount
, then checking the keystrokes with the Where
.
I tried using BufferWithTime, but it tends to cut in the middle of keystrokes.
If somebody can suggest improvements, I would love to hear them.
I don't want to spoil the answer for you since you're learning, but I would try to think of the problem as, "How can I transform the Key up event into the sequence of the last 10 characters that were recently pressed", and compare that list to the constant list of "UUDDLRLRBA". (Hint: Buffer, Where, Select, Take, Repeat are your friends here)
To update the answer from Endy (in RxJS 7) (with sequenceEqual from rxjs sample, because, smart usage of it :D)
const table: {[key: string]: number} = {
ArrowUp: 38,
ArrowDown: 40,
ArrowLeft: 37,
ArrowRight: 39,
KeyB: 66,
// Azerty compat
KeyQ: 65,
KeyA: 65,
};
const knownSequence = from([38, 38, 40, 40, 37, 39, 37, 39, 66, 66]);
const konami$ = fromEvent<KeyboardEvent>(document, 'keyup').pipe(
map((e) => table[e.code] ? table[e.code] : -1),
skipWhile((k) => k !== 38),
bufferCount(10, 1),
mergeMap((x) => {
return from(x).pipe(sequenceEqual(knownSequence));
}),
filter((sequenceEqual) => sequenceEqual),
switchMap((_) => of('konami'))
);
// Basic usage (promisified)
await firstValueFrom(konami$);
// Do Konami thing
精彩评论