【问题标题】:Detect and print key combinations Javascript检测和打印组合键 Javascript
【发布时间】:2020-10-12 21:38:46
【问题描述】:

我目前正在尝试将用户提供的键盘组合转换为其可打印版本(例如,如果用户按下 shift + a,我希望能够检测到它并在某处打印字符串“shift + a”,以便用户知道他与操作相关联的组合。

到目前为止,我一直在使用提供的布尔值:ctrlKey、altKey、shiftKey 和 metaKey,当它们为真时,我将它们的可打印版本添加到最终字符串中。

它在某种程度上......在某种程度上......

我正确收到了 ctrl 标志,但是 shift 标志不稳定(在不应该换班的时候不给班次,但在应该换班的时候不给班次,尽管它对某些键工作正常)并且 alt 标志似乎只对少数几个有效键和元标志似乎根本不起作用。 请注意,我的键盘工作正常,也就是说,这些键在正常情况下按预期工作(shift 键允许我大写,win 键允许我锁定我的计算机,等等...) 另请注意,我的键盘是 azerty。

它在 W3schools 示例中的行为方式相同:

https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_event_key_shiftkey

这是一个例子:

trying with &, which does not require shift on an azerty

trying with 1, which does require shift on an azerty

所以我认为我在检测组合键的方式上存在一些误解。感谢所有愿意提供帮助的人。

function logKey(e) {
    var modifier1;
    var modifier2;
    var modifier3;
    var modifier4;
    var display = "";

    if (e.ctrlKey) {
        modifier1 = "ctrl + ";
    }
    else {
        modifier1 = "";
    }
    if (e.altKey) {
        modifier2 = "alt + ";
    }
    else {
        modifier2 = "";
    }
    if (e.shiftKey) {
        modifier3 = "shift + ";
    }
    else {
        modifier3 = "";
    }      
    if (e.metaKey) {
        modifier4 = "meta + ";
    }
    else {
        modifier4 = "";
    }

    display = modifier1 + modifier2 + modifier3 + modifier4 + e.key

    window.alert(display);
}
window.addEventListener('keydown', logKey);

【问题讨论】:

  • 您最好保留一张已关闭的键映射(包括修饰符),而不是依赖事件信息。
  • 我广泛使用了键盘事件,但从未听说过布尔值“不稳定”。但是,您使用的键盘可能正在“重新映射”& 到 shift+7(这是 QWERTY 键盘上的键盘)。
  • 我在这里肯定看到了时间问题。例如,如果您只是按“Ctrl”并在几毫秒后按“A”键,您的代码将触发 two keydown 事件。 -> 这会导致你意想不到的行为。更多需要考虑 - 如果您一次或多次按 3 个键,如果您只按一个会怎样? - 有很多事情要考虑...

标签: javascript keydown


【解决方案1】:

正如 skyline3000 在他们的评论中暗示的那样,您最好独立跟踪按下了哪些键,然后在需要它们时,只需查看您跟踪的内容。

类似这样的:

const input = document.querySelector('input');
const keysDown = [];

input.addEventListener('keydown', e => {
  if (keysDown.indexOf(e.keyCode) === -1) {
    keysDown.push(e.keyCode);
  }
  
  console.log(keysDown);
});

input.addEventListener('keyup', e => {
  const index = keysDown.indexOf(e.keyCode);
  
  if (index !== -1) {
    keysDown.splice(index, 1);
  }
  
  console.log(keysDown, e);
});
Focus on input to register keys:
<input />

这将使您可以更精确地跟踪它们,甚至可以一次跟踪很多键。

然后,当您想显示他们按下了哪些键时,您只需打印出您的 keysDown 列表。

【讨论】:

  • 最大的问题是如果你 Alt+Tab,那么你的代码永远不会被通知 Alt 被释放。
  • 确实如此,但这对于任何应用程序来说都是一种边缘情况。当我像这样跟踪键时,我几乎总是清除window blur 上的整个列表。
  • 您可以在窗口上添加一个模糊事件侦听器,用于当窗口失去焦点并重置地图时,或者在窗口焦点上进行类似的操作。
  • 当然,但是当altKey 等已经存在并且(应该!)100% 的时间都有效时,这似乎是一个巨大的黑客攻击。
  • 是的,但它还涉及更多代码来处理所有修饰符(就像上面的原始问题一样)。使用这种方法,您只需要一个键列表,这些键实际上并不重要,您可以随后输出它们。另外,无论如何,您都不会在应用程序中通过键绑定“alt+tab”来执行某些操作。
【解决方案2】:

所以...

我今天回到问题上,意识到问题甚至不限于这些布尔值。即使我忽略布尔值并尝试使用键码来注册被按下的修饰键,这也不起作用(使用@samanime 代码),至少在 Firefox 上不起作用,因为显然我的 Firefox 不会触发 keydown/keyup(或 keypress)当我按下 ctrl 或 alt 等修饰键时的事件。它确实会在其他键上正常触发,例如字符键。

它可以在 Chrome 上运行。

是否存在一些我不知道的兼容性问题?还是我的 Firefox 有问题?

【讨论】:

    【解决方案3】:

    非常简单的解决方案:

    let keys = {};
    let keysPressed = '';
    
    document.onkeydown = handleKey;
    document.onkeyup = handleKey;
    
    function handleKey(e) {
      // Indicate key pressed
      if (e.type == 'keydown') {
        keys[e.key] = true;
      }
      else {
        keys[e.key] = false;
      }
    
      // Run on all keys and determine which are pressed
      keysPressed = '';
      for (const [key, value] of Object.entries(keys)) {
        if (value) {
          keysPressed += key;
        }
      }
    
      // Show key presses
      document.querySelector('.keys').innerHTML = keysPressed;
    }
    &lt;div class="keys"&gt;Press some keys&lt;/div&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-09
      • 1970-01-01
      • 2018-06-20
      • 2012-01-22
      相关资源
      最近更新 更多