【发布时间】:2011-06-24 16:11:03
【问题描述】:
有没有办法让 jQuery 检测到同时按下了多个键?
是否有任何替代方法可以检测同时按下两个键?
【问题讨论】:
标签: javascript jquery
有没有办法让 jQuery 检测到同时按下了多个键?
是否有任何替代方法可以检测同时按下两个键?
【问题讨论】:
标签: javascript jquery
为了检测多个键被按下,使用keydown 和keyup 事件。
var keys = {};
$(document).keydown(function (e) {
keys[e.which] = true;
});
$(document).keyup(function (e) {
delete keys[e.which];
});
我在这里做了一个演示:http://jsfiddle.net/gFcuU/。这很有趣,虽然我注意到我的键盘最多只能检测 6 个键。
【讨论】:
printKeys 循环中节省一些迭代。但在实践中,你是对的,这是一个很小的差异。
这取决于。对于“普通”键,这意味着非 Shift、Ctrl、ALT、(CMD),答案否,事件处理程序将一个接一个地在队列中捕获/触发。
对于我上面提到的修饰键,事件对象上有一个属性。
例子:
$(document).bind('keypress', function(event) {
if( event.which === 65 && event.shiftKey ) {
alert('you pressed SHIFT+A');
}
});
其他属性是:
event.ctrlKeyevent.altKeyevent.metaKey【讨论】:
metaKey 设置为 true,用于 alt、shift、ctrl 和 cmd。值得注意的是keypress 不会为CMD 触发。但是对于keydown,例如
metaKey 适用于 ctrl 和 cmd。
如果您只想在连续按下多个键时触发处理程序,请尝试以下操作:
jQuery.multipress = function (keys, handler) {
'use strict';
if (keys.length === 0) {
return;
}
var down = {};
jQuery(document).keydown(function (event) {
down[event.keyCode] = true;
}).keyup(function (event) {
// Copy keys array, build array of pressed keys
var remaining = keys.slice(0),
pressed = Object.keys(down).map(function (num) { return parseInt(num, 10); }),
indexOfKey;
// Remove pressedKeys from remainingKeys
jQuery.each(pressed, function (i, key) {
if (down[key] === true) {
down[key] = false;
indexOfKey = remaining.indexOf(key);
if (indexOfKey > -1) {
remaining.splice(indexOfKey, 1);
}
}
});
// If we hit all the keys, fire off handler
if (remaining.length === 0) {
handler(event);
}
});
};
例如,要在 s-t 上开火,
jQuery.multipress([83, 84], function () { alert('You pressed s-t'); })
【讨论】:
不。 keypress 将针对每个按下的单独键触发 - 除了 CTRL、ALT 和 SHIFT 等修饰键之外,您可以将它们与其他键组合,只要它只是一个其他键。
【讨论】:
这是一个基于 jQuery 的解决方案 Maciej 的回答https://stackoverflow.com/a/21522329/
// the array to add pressed keys to
var keys = [];
// listen for which key is pressed
document.addEventListener('keydown', (event) => {
if ($.inArray(event.keyCode, keys) == -1) {
keys.push(event.keyCode);
}
console.log('keys array after pressed = ' + keys);
});
// listen for which key is unpressed
document.addEventListener('keyup', (event) => {
// the key to remove
var removeKey = event.keyCode;
// remove it
keys = $.grep(keys, function(value) {
return value != removeKey;
});
console.log('keys array after unpress = ' + keys);
});
// assign key number to a recognizable value name
var w = 87;
var d = 68;
var s = 83;
var a = 65;
// determine which keys are pressed
document.addEventListener('keydown', (event) => {
if ($.inArray(w, keys) != -1 && $.inArray(d, keys) != -1) { // w + d
console.log('function for w + d combo');
} else if ($.inArray(s, keys) != -1 && $.inArray(a, keys) != -1) { // s + a
console.log('function for s + a combo');
}
})
小提琴演示
【讨论】:
如果您使用的是 esma6,则可以使用集合执行以下操作。
const KEYS = new Set();
$(document).keydown(function (e) {
KEYS.add(e.which);
if(KEYS.has(12) && KEYS.has(31)){
//do something
}
});
$(document).keyup(function (e) {
KEYS.delete(e.which);
});
如果您希望用户将它们按在一起,您可以这样做:
const KEYS = new Set(); // for other purposes
const RECENT_KEYS = new Set(); // the recently pressed keys
const KEY_TIMELAPSE = 100 // the miliseconds of difference between keys
$(document).keydown(function (e) {
KEYS.add(e.which);
RECENT_KEYS.add(e.which);
setTimeout(()=>{
RECENT_KEYS.delete(e.which);
}, KEY_TIMELAPSE);
if(RECENT_KEYS.has(37) && RECENT_KEYS.has(38)){
// Do something
}
});
$(document).keyup(function (e) {
KEYS.delete(e.which);
RECENT_KEYS.delete(e.which);
});
这是一个代码笔https://codepen.io/Programador-Anonimo/pen/NoEeKM?editors=0010
【讨论】:
由于我的要点已过期(没有人使用它 :()我决定用更多 2017 解决方案更新答案。请查看以下内容。
您可以使用我的 jquery 插件来检测快捷方式。
它基本上会缓存事件并获取当前按下的键。如果按下所有键,则触发功能。
https://github.com/maciekpaprocki/bindShortcut(已过期!)
您在自述文件中简要说明了如何使用它。希望这可以帮助。反馈多于赞赏。
2017 年编辑:
现在是 2017 年,我们不需要 jQuery 插件来解决这样的问题。简而言之,您将需要这样的东西:
let pressed = {};
document.addEventListener('keydown', (event) => {
pressed[event.key] = true;
});
document.addEventListener('keyup', (event) => {
delete pressed[event.key];
});
//and now write your code
document.addEventListener('keydown', (event) => {
if(pressed[firstKey]&&pressed[secondKey]){
//dosomething
}
});
较旧的浏览器可能有一些怪癖,但是从 IE9 开始,除了少数不支持正确事件委托的操作系统(超级旧的 ubuntu 等)外,一切都应该可以正常工作。没有办法在它们中解决这个问题,因为这不是浏览器问题。
在连接到布尔键的新 Mac 中有一些怪癖,例如大写锁定。
阅读更多:https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names_and_Char_values
【讨论】:
根据@David Tang 的解决方案,这里有一个快速而肮脏的自定义捕获 Shift+Ctrl+A 组合:
var pressedKeys = {};
function checkPressedKeys() {
var shiftPressed=false, ctrlPressed=false, aPressed=false;
for (var i in pressedKeys) {
if (!pressedKeys.hasOwnProperty(i)) continue;
if(i==16){
shiftPressed=true;
}
else if(i==17){
ctrlPressed=true;
}
else if(i==65){
aPressed=true;
}
}
if(shiftPressed && ctrlPressed && aPressed){
//do whatever you want here.
}
}
$(document).ready(function(){
$(document).keydown(function (e) {
pressedKeys[e.which] = true;
checkPressedKeys();
});
$(document).keyup(function (e) {
delete pressedKeys[e.which];
});
});
【讨论】: