我试图使用RxJS捕捉用户的击键,并为每一笔生成一个结果对象,该对象包含键、笔画的工期( keyup和keydown事件之间的时间)和以前笔画之间的间隔(使用timeInterval)。有关概述,请参见下面的图像。
到目前为止,我的代码正在工作:Hello输出ShiftLeftHELLO。
但是,当我编写更快的时(我的意思是),一切都会崩溃,World输出ShiftLeftShiftLeftOLD。
您对在我的代码中实现背压、缓冲或其他东西以防止这种行为有什么建议吗?
(function (document) {
var textarea = document.querySelector("#input");
var keyUpStream = Rx.DOM.keyup(textarea);
var keyDownStream = Rx.DOM.keydown(textarea);
var keyStrokeStream = Rx.Observable.merge(keyDownStream, keyUpStream);
var keystroke = keyStrokeStream.filter((function() {
var keysPressed = {};
return function(e) {
var k = 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;
}
}
};
})())
.distinctUntilChanged(function (e){
return e.type + e.which;
})
.timeInterval()
.bufferWithCount(2)
.zip(function (evts){
return {
"ts" : Date.now(),
"key": evts[0].value.code,
"evts" : evts,
"duration" : evts.reduce(function(a, b){
return b.value.timeStamp - a.value.timeStamp;
})
};
}).subscribe(function (e){
console.log(e);
document.querySelector("#output").textContent += e.key.replace("Key", '');
document.querySelector("#console").textContent += JSON.stringify(e);
});
})(document);<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.1.0/rx.all.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs-dom/7.0.3/rx.dom.js"></script>
<h1>KeyStroke</h1>
<textarea id="input" rows="5" cols="50"></textarea>
<div id="output"></div>
<div id="console"></div>

发布于 2016-03-29 11:06:13
免责声明: Rxjs noob在这里。
问题是,您的代码期望从一个键到一个键,然后再从那个键中按下一个键。键入“快”时,在击键时会出现争用条件,从而产生带有多个按键或密钥的缓冲区。不是你在缓冲区里期望的那样。
我已经修改了代码以利用您的过滤器功能。该函数只返回keyup事件,并保存相应的按键笔画。这样,就可以计算过滤器函数中的间隔。我确信有一个更优雅的解决方案,只使用RxJS函数,但是由于您已经在过滤器函数中使用了状态,所以我对它做了一些修改。
这个片段现在显示了一个正确的输出。我认为它解决了您的问题,但它不是使用RxJS的好方法(正如我所说的,我们将状态存储在过滤器函数中)。
(function (document) {
var textarea = document.querySelector("#input");
var keyUpStream = Rx.DOM.keyup(textarea);
var keyDownStream = Rx.DOM.keydown(textarea);
var keyStrokeStream = Rx.Observable.merge(keyDownStream, keyUpStream);
var keystroke = keyStrokeStream.filter((function() {
var keysPressed = {};
return function(e) {
var key = e.which;
var result;
if (e.type == 'keyup' && keysPressed.hasOwnProperty(key)) {
e.strokeInterval = Date.now() - keysPressed[key];
delete keysPressed[key];
return true;
} else if (e.type == 'keydown') {
if (!keysPressed.hasOwnProperty(key)) {
keysPressed[key] = Date.now();
}
return false;
}
return false;
};
})())
.map(function (evt){
return {
"ts" : Date.now(),
"key": evt.code,
"duration" : evt.strokeInterval
};
})
.subscribe(function (e){
console.log(e);
document.querySelector("#output").textContent += e.key.replace("Key", '');
document.querySelector("#console").textContent += JSON.stringify(e);
});
})(document);<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.1.0/rx.all.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs-dom/7.0.3/rx.dom.js"></script>
<h1>KeyStroke</h1>
<textarea id="input" rows="5" cols="50"></textarea>
<div id="output"></div>
<div id="console"></div>
https://stackoverflow.com/questions/36224872
复制相似问题