2015-07-03 34 views
2

我需要獲得乾淨的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 
}); 

如何適應它做的工作嗎?

+0

我不明白你想過濾。重複密碼是什麼意思?你是否想把鑰匙與鑰匙相提並論? – paulpdaniels

+0

當你按下一個鍵並按住它時,通常你會得到重複,很多keydowns。當按鍵被按下時,我想要1'按'事件,並且當按鍵被釋放時,'1'釋放'事件。對不起,我的英語 –

+0

而且,是的,需要匹配鍵盤和keydowns之間的匹配 –

回答

5

查看費德里科的答案,下面是一個更優雅和習慣解決方案。


可避免重複項目從可觀察到的(正如你看到的,當某個鍵)與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風格。 (任何意見讚賞。)

+0

雖然這可行,但具有狀態跟蹤的代碼非常**單一。 –

+0

同意。解決方案編輯爲參考。 – icio

9

雖然它很好,它的工作原理,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版本。按事件類型進行操作,以便跳過額外的關鍵字。
  • 合併所有的鑰匙回到一個可觀察的