我有一个物理引擎,该引擎会每帧更新一次,我有一个带有轮子的车辆,我想通过使用一些箭头键来控制。
作为一种蛮力方法,我创建了4个Listeners
,每个箭头键都这样一个:
按下键时...
fromEvent(document, KEY_DOWN)
.pipe(
filter(e => e.keyCode === KEYS.UP),
filter(e => !e.repeat)
)
.subscribe(() => {
...
updateSpeed(...)
});
以及释放键时...
fromEvent(document, KEY_UP)
.pipe(filter(e => e.keyCode === KEYS.UP))
.subscribe(() => {
...
updateSpeed(...) // set speed back to 0
});
它有效,但是看起来很乏味,因为我必须为每个键(总共8个侦听器)创建一个keydown
侦听器和一个keyup
侦听器。有没有办法合并事件,有一个单一且更优雅的控制器?
是,您应该查看combineLatest
或组合运算符(https://scotch.io/tutorials/rxjs-operators-for-dummies-forkjoin-zip-combinelatest-withlatestfrom)之一。
这不是一个完整的答案,但可以帮助您入门
import { combineLatest } from 'rxjs';
...
x = combineLatest(
fromEvent(document, KEY_DOWN).pipe(
filter(e => e.keyCode === KEYS.UP || /* Allow the other 3 keys with or statements */),
filter(e => !e.repeat),
startWith(null),
),
fromEvent(document, KEY_UP).pipe(
filter(e => e.keyCode === KEYS.UP || /* Allow the other 3 keys with or statements */)),
startWith(null),
)
).subscribe(([keyDown, keyUp]) => {
// you have access to keyDown and keyUp events here. Make sure they are truthy since we startWith null and see their values and do the appropriate actions
});
....
x.unsubscribe();
I startWith
为null,因为combineLatest
,每个可观察对象必须至少发射一次以启动流,因此它将启动流。您可能需要四处摸索才能获得所需的结果。
此外,由于您正在订阅events
,因此从订阅中订阅unsubscribe
对您来说非常重要,因为事件不是有限的,并且这可能导致意外行为(即使此代码,订阅也会对每个按键进行反应不是“有效”)。
==========================编辑=================== ===我认为merge
甚至是更好的方法。
import { merge } from 'rxjs';
x = merge(
fromEvent(document, KEY_DOWN).pipe(
filter(e => e.keyCode === KEYS.UP || /* Allow the other 3 keys with or statements */),
filter(e => !e.repeat),
),
fromEvent(document, KEY_UP).pipe(
filter(e => e.keyCode === KEYS.UP || /* Allow the other 3 keys with or statements */)),
)
).subscribe(keyUpOrKeyDown => {
// now you have a handle on the event and can do the appropriate action accordingly
});
....
x.unsubscribe();
我发现这样更好,因为您不需要startWith(null)