JavaScript - 获取任何键盘布局的按键描述

12

为了实现一个功能丰富的Web应用程序,我需要键盘快捷键。由于存在许多不同的键盘布局,它们必须是可配置的。不幸的是,我无法找到一种将键盘事件映射到人类可读的快捷键名称(例如Ctrl + Alt + YAlt + \)的方法。

keypress事件对所有键都无效。以下是keydown事件的一些属性:

  • charCode:仅适用于可打印字符。 根据MDN,已弃用
  • code:有效,但忽略键盘布局。当我按Z键时,在我的德语键盘上我得到code: "KeyY"
  • key:有效,但基于修饰符会产生不同的结果。例如,Shift + 3在我的键盘上产生key: "§",在大多数美国键盘上产生key: "#"
  • keyCode:该值不唯一。 Ä、Ö、Ü 或 ^ 的keyCode均为0。根据MDN,已弃用
  • which:与keyCode一样,该值不唯一。根据MDN,已弃用
  • altKeyctrlKeymetaKeyshiftKey:用于检测修饰键

我该如何做呢?即使不知道用户的键盘布局,这是否可能?


1
这个库对你有帮助吗?https://github.com/ccampbell/mousetrap - Tarun Lalwani
还没有尝试过,不过看起来很有前途! - Aloso
@TarunLalwani 插件正常运行,谢谢! - Aloso
很好,我会在几个小时后将其作为答案发布。 - Tarun Lalwani
3个回答

5
事实是,此时您无法从浏览器内部了解键盘布局,只能猜测和推测。有各种方法可以尝试某种类型的检测,但它们始终是复杂的,并且不是开箱即用的解决方案。
但是,有一些事情可以做,以某种方式确定按下了哪个键。
因此,KeyDown将为您提供(假设事件对象为e):
- e.code: 保存标识正在按下的物理键的字符串。该值不受当前键盘布局或修改器状态的影响,因此特定键始终返回相同的值。(来自mozilla.org) - e.key: 由事件表示的键的键值。如果该值具有打印表示,则此属性的值与char属性的值相同。 - e.which和e.keyCode:虽然已弃用,但会为您提供键盘上的位置代码,如果e.charCode为0,则这是位置代码(如果<256)或Unicode(这意味着键盘切换到另一种语言)
现在这里的棘手部分是,如果e.key可打印且不来自美国键盘并且不是特殊键,则实际上表示Unicode字符。您可以将此字符转换为十进制数并检查该值。如果它是Unicode字符,则其十进制值将等于which和keyCode值。如果是普通ASCII,则其小写值将等于which和keyCode值。此外,在执行此操作(转换)之前,您可以检查e.key是否为字符串(如Control、Alt、CapsLock等)或字符(如a、b、c等)。因此,如果它是一个字符,那么您将其转换。
所有这些都将使您了解哪个键已被按下以及该键的本机可打印字符是什么。我没有德语、意大利语或其他语言的键盘进行测试,但您明白我的意思。
哦,如果您担心Shift+3会产生“§”或“#”,则无论它产生的字符是什么,您都应该始终将其表示为Shift+3,更不用说相同的组合将通过Ctrl+Shift+3产生。您只需要担心字母字符,但我相信我已经给您检查它们的方法了。
此外,我认为您甚至可能不需要e.which和e.keyCode,因为e.key应该为您提供一切。

2
我认为你的问题不是问题,而只是对问题的错误分析,而且你已经有了答案!
你说你想定义“可读性强的快捷方式”,并且拒绝使用“键”属性,因为当用户按下Shift+3时,键值是“§”,我认为你期望的键值是3。
问题是“什么是可读性强的?”。
按下“§”并获得“§”或者开发人员说当他按下Shift+3时,他获得“§”而不是Shift+3,这是不正常的。
但是如果用户按下“§”或Shift+3(在你的德语键盘上),键值等于“§”是正常的,你可以使用keydown事件来截取用户仅按下“3”或“§”时的操作。
在我的法语键盘上,我有一个与数字“2”相同的键“é”。如果我按下键“é”(或2),我会得到字符“é”。如果我按下Shift+2(或Shift+é),我会得到一个数字“2”。
我可以使用keydown事件来截取Ctrl+é和Ctrl+2(=Ctrlt+Shift+2)而没有问题。
我认为你可以使用keydown事件来截取“§”。截取Shift+3是不可能的,因为shift+3等同于“§”。
如果你的目标是独立于键盘布局拦截SHIFT+DIGIT键,你可以添加一些JavaScript代码来为数字键创建一些例外情况(或过滤器),我认为对于其他键不必要。
在这种情况下,您可以考虑使用keyCode属性来拦截按下数字键。
在所有情况下,尝试知道键盘的布局是不必要的。
目前,我使用法语/法语、法语/比利时语、法语/瑞士语和美国/美国键盘(或Tastatur)工作,并且20年前写C++ ActiveControl时遇到了同样的问题。
如果我的答案对你来说还不够好,请提供一些例子,这样我就可以帮助你解决这些特定的新问题。

2

与其重新发明轮子,我宁愿使用一个已经做到这一点的跨浏览器库。

https://github.com/ccampbell/mousetrap

为避免仅提供链接的回答,我无法在此处粘贴完整的JavaScript代码,因为如果允许字符数超过限制。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接