如何使用rxjs过滤keydowns?
我需要获得干净的keydown/keyup事件而无需重复。当你按下一个按键keydown事件发生时,当你释放 - 键入。没有凌乱的重复keydowns。如何使用rxjs过滤keydowns?
这里是代码:
var keyDowns = rx.Observable.fromEvent(document, 'keydown');
var keyUps = rx.Observable.fromEvent(document, 'keyup');
var keyActions = rx.Observable.merge(keyDowns, keyUps);
keyActions.subscribe(function(e) {
console.log e
});
如何适应它做的工作吗?
查看费德里科的答案,下面是一个更优雅和习惯解决方案。
可避免重复项目从可观察到的(正如你看到的,当某个键)与distinctUntilChanged
过滤掉匹配最后发出的值(其中匹配由发射值或它们的值相等确定的值由keySelector
回调参数转换)。
在你的情况,这可能看起来那么简单,有点像:
var keyDowns = Rx.Observable.fromEvent(document, 'keydown');
var keyUps = Rx.Observable.fromEvent(document, 'keyup');
var keyActions = Rx.Observable
.merge(keyDowns, keyUps)
.distinctUntilChanged(function(e) { return e.type + (e.key || e.which); });
keyActions.subscribe(function(e) {
console.log(e.type, e.key || e.which, e.keyIdentifier);
});
但这持有多个键时达不到。在Chrome OS X,如果我按住A,S,d,然后释放A,S,DI在控制台中执行以下操作:
keydown 65 U+0041
keydown 83 U+0053
keydown 68 U+0044
keyup 65 U+0041
keydown 68 U+0044
keyup 83 U+0053
keydown 68 U+0044
keyup 68 U+0044
注 “的keydown 68”(d)的重复时释放A和S.这是因为事件仅针对最近按下的键重复。使用类似的想法告诉了一个在您的评论中,我们可以改为尝试一个自定义过滤器,维护着这个键被按下列表:
var keyDowns = Rx.Observable.fromEvent(document, 'keydown');
var keyUps = Rx.Observable.fromEvent(document, 'keyup');
var keyActions = Rx.Observable
.merge(keyDowns, keyUps)
.filter((function() {
var keysPressed = {};
return function(e) {
var k = e.key || e.which;
if (e.type == 'keyup') {
delete keysPressed[k];
return true;
} else if (e.type == 'keydown') {
if (keysPressed[k]) {
return false;
} else {
keysPressed[k] = true;
return true;
}
}
};
})());
keyActions.subscribe(function(e) {
console.log(e.type, e.key || e.which, e.keyIdentifier);
});
按住A,S,d,然后释放, S,d现在给:
keydown 65 U+0041
keydown 83 U+0053
keydown 68 U+0044
keyup 65 U+0041
keyup 83 U+0053
keyup 68 U+0044
除了我们过滤合并流而不是预先过滤,使得组合流看起来我们喜欢它,这类似于你在注释中提到的方法。
我对rx.js没有足够的经验,断言这是做到这一点的最好方法,但它肯定会感觉更符合Rx风格。 (任何意见赞赏。)
虽然这可行,但具有状态跟踪的代码非常**单一。 –
同意。解决方案编辑为参考。 – icio
虽然它很好,它的工作原理,icio与状态跟踪的解决方案是**非常** unidiomatic。正确RxJs 5的解决办法是:
var keyDowns = Rx.Observable.fromEvent(document, "keydown")
var keyUps = Rx.Observable.fromEvent(document, "keyup")
var keyPresses = keyDowns
.merge(keyUps)
.groupBy(e => e.keyCode)
.map(group => group.distinctUntilChanged(null, e => e.type))
.mergeAll()
说明:
- 合并所有键所有的keydown和KeyUp事件。
- 按键(keyCode)对它们进行分组。它创建一个可观察的可观察对象,每个可观察对象将包含一个关键点的所有事件。
- 将每个子观察对象映射到它自己的distinctUntilChanged版本。按事件类型进行操作,以便跳过额外的关键字。
- 合并所有的钥匙回到一个可观察的
我不明白你想过滤。重复密码是什么意思?你是否想把钥匙与钥匙相提并论? – paulpdaniels
当你按下一个键并按住它时,通常你会得到重复,很多keydowns。当按键被按下时,我想要1'按'事件,并且当按键被释放时,'1'释放'事件。对不起,我的英语 –
而且,是的,需要匹配键盘和keydowns之间的匹配 –