一个现代化、类型安全的 JavaScript 类,用于监听和处理键盘组合键事件。支持复杂的键盘操作序列检测,如快捷键、秘籍码等。
可用于游戏开发、Web 应用快捷键、隐藏功能激活等场景,灵感来自 thisisunsafe 浏览器绕过告警提示的隐藏指令。
游戏中使用了 ComboKeys 来监听玩家的 ↑ ↓ ← → 移动和 Space 攻击按键
留下了一些隐藏指令,如 TIPS 显示钥匙位置,或再输入 EASY 标记最佳路径
哦对了!我依旧保留了那个经典彩蛋,试试 ↑↑↓↓←→←→BA 并输入 AUTO 吧!
// 创建一个监听 Ctrl+C 的组合键
const combo = new ComboKeys(["ControlLeft", "KeyC"])
.onTrigger(() => {
console.log("复制快捷键被触发!");
})
.start();
// 监听复杂的按键序列(科乐美秘籍)
const konamiCode = new ComboKeys(["ArrowUp", "ArrowUp", "ArrowDown", "ArrowDown", "ArrowLeft", "ArrowRight", "ArrowLeft", "ArrowRight", "KeyB", "KeyA"])
.timeout(800) // 800ms 内完成
.onTrigger((info) => {
console.log(`科乐美秘籍激活!第 ${info.triggerCount} 次`);
}, false) // 不阻止方向键默认行为
.maxTriggers(3) // 最多触发3次
.debug(true) // 开启调试模式
.start();
const advancedCombo = new ComboKeys({
keys: ["AltLeft", "ShiftLeft", "KeyF"],
timeout: 1500,
target: document.body,
preventDefault: true,
maxTriggers: 5,
debug: true,
})
.onTrigger((info) => {
console.log("高级组合键触发", info);
})
.start();
// 阻止默认行为(默认)
const combo1 = new ComboKeys(["ControlLeft", "KeyS"]).onTrigger(() => console.log("保存")).start();
// 允许默认行为
const combo2 = new ComboKeys(["ControlLeft", "KeyC"])
.onTrigger(() => console.log("复制"), false) // 第二个参数为false
.start();
// 输入框中的组合键,通常不阻止默认行为
const inputCombo = new ComboKeys(["ControlLeft", "Enter"])
.target(document.getElementById("input"))
.onTrigger(() => console.log("提交"), false)
.start();
// 方式一:数组 + 选项对象
new ComboKeys(keys, options);
// 方式二:配置对象
new ComboKeys(config);
参数说明:
keys (Array): 按键代码数组,如 ['ControlLeft', 'KeyC']options/config (Object): 配置选项
keys (Array): 按键序列timeout (Number): 按键间超时时间,默认 1000mstarget (Element): 监听目标,默认 documentpreventDefault (Boolean): 是否阻止默认行为,默认 truemaxTriggers (Number): 最大触发次数,默认 Infinitydebug (Boolean): 是否开启调试,默认 falsekeys(keyArray)设置按键序列
combo.keys(["ControlLeft", "KeyC"]);
timeout(milliseconds)设置按键间超时时间
combo.timeout(500); // 设置为500ms
onTrigger(callback, preventDefault)设置触发回调函数
combo.onTrigger((info) => {
console.log("触发了!", info);
// info 包含: { event, triggerCount, timestamp }
}, true); // 阻止默认行为(可选,默认true)
// 允许默认行为
combo.onTrigger(callback, false);
target(element)指定监听目标元素
combo.target(document.getElementById("myDiv"));
maxTriggers(count)设置最大触发次数
combo.maxTriggers(3); // 最多触发3次
debug(enabled)开启或关闭调试模式
combo.debug(true); // 输出详细调试信息
start()开始监听按键事件
combo.start(); // 开始监听
stop(destroy)停止监听按键事件
combo.stop(); // 停止监听
combo.stop(true); // 停止监听并销毁实例
reset()重置当前匹配状态
combo.reset(); // 清除已匹配的按键序列
getStatus()获取当前状态信息
const status = combo.getStatus();
console.log(status);
// 返回: {
// isListening: true,
// progress: "2/4",
// triggerCount: 1,
// maxTriggers: 3,
// keys: ['KeyA', 'KeyB'],
// target: document
// }
ComboKeys 2.0 采用了现代化的面向对象设计,融合了多种设计模式:
keydown 和 keyup 事件,提供完整的按键生命周期控制matchedKeys、lastKeyTime、triggerCountthis当检测到修饰键(Ctrl、Alt、Shift、Meta)时自动启用:
// 这些会被识别为组合键模式
["ControlLeft", "KeyC"][("AltLeft", "Tab")][("ControlLeft", "ShiftLeft", "KeyZ")]; // Ctrl+C // Alt+Tab // Ctrl+Shift+Z
普通按键会被识别为序列模式:
// 这些会被识别为序列模式
["KeyH", "KeyE", "KeyL", "KeyL", "KeyO"][("ArrowUp", "ArrowUp", "ArrowDown")][("KeyA", "KeyB", "KeyC")]; // H-E-L-L-O // ↑↑↓ // A-B-C
// 内部编码规则
{
keydown: '+', // 按键按下前缀
keyup: '-' // 按键释放前缀
}
// 组合键模式:只监听按下事件
['ControlLeft', 'KeyC'] → ['+ControlLeft', '+KeyC']
// 序列模式:监听按下和释放事件
['KeyA', 'KeyB'] → ['+KeyA', '-KeyA', '+KeyB', '-KeyB']
// 参数类型验证
if (!Array.isArray(keys)) {
throw new TypeError("按键序列必须是数组类型");
}
// 运行时错误捕获
try {
this.config.callback.call(this, info);
} catch (error) {
console.error("ComboKeys 回调函数执行错误:", error);
}
stop(true) 支持完全销毁实例capture: true 确保事件正确移除reset() 方法清理中间状态// ❌ 旧版本:方法名不够直观
combo.do(callback).on();
// ✅ 新版本:语义明确
combo.onTrigger(callback).start();
// 所有配置方法都返回 this,支持链式调用
combo.keys([...]).timeout(1000).onTrigger(...).start();
// 重复调用 start() 不会出错
combo.start().start(); // 第二次调用会输出警告但不抛异常
// 静态常量便于扩展
static KEY_SYMBOLS = { keydown: '+', keyup: '-' };
static DEFAULT_OPTIONS = { /* ... */ };
// 格斗游戏招式系统
const hadoken = new ComboKeys(["ArrowDown", "ArrowRight", "KeyP"])
.timeout(500)
.onTrigger(() => this.castFireball(), false) // 允许方向键滚动页面
.start();
// 编辑器快捷键(通常需要阻止默认行为)
const shortcuts = [
new ComboKeys(["ControlLeft", "KeyS"]).onTrigger(() => saveDocument()),
new ComboKeys(["ControlLeft", "KeyZ"]).onTrigger(() => undo()),
new ComboKeys(["ControlLeft", "ShiftLeft", "KeyZ"]).onTrigger(() => redo()),
].map((combo) => combo.start());
// 开发者工具激活
const devMode = new ComboKeys(["KeyD", "KeyE", "KeyV"])
.timeout(2000)
.onTrigger(() => toggleDeveloperMode(), false) // 允许字母输入
.maxTriggers(1)
.start();
// 管理员面板访问
const adminAccess = new ComboKeys(["KeyA", "KeyD", "KeyM", "KeyI", "KeyN"])
.timeout(3000)
.onTrigger(() => showAdminPanel(), false) // 允许正常输入
.maxTriggers(3)
.start();
try {
const combo = new ComboKeys(["ControlLeft", "KeyC"]).onTrigger(() => console.log("复制")).start();
} catch (error) {
console.error("组合键创建失败:", error.message);
}
// 完全阻止默认行为(默认)
combo.onTrigger(callback);
// 显式阻止默认行为
combo.onTrigger(callback, true);
// 允许默认行为
combo.onTrigger(callback, false);
// 页面卸载时清理资源
window.addEventListener("beforeunload", () => {
comboInstances.forEach((combo) => combo.stop(true));
});
// 定期检查组合键状态
setInterval(() => {
const status = combo.getStatus();
if (status.progress !== "0/4") {
console.log(`进度: ${status.progress}`);
}
}, 1000);
// 根据应用状态控制监听
if (isGameMode) {
gameCombo.start();
} else {
gameCombo.stop();
}
| 特性 | 支持情况 |
|---|---|
| 浏览器 | Chrome 51+, Firefox 54+, Safari 10.1+, Edge 79+ |
| Node.js | 不支持(需要 DOM 环境) |
| TypeScript | 兼容(提供类型推导) |
| ES 模块 | 支持 |
| CommonJS | 支持 |
技术依赖:
KeyboardEvent.code 属性// ES6 模块
import ComboKeys from "./ComboKey.js";
// CommonJS
const ComboKeys = require("./ComboKey.js");
// 直接引入
<script src="ComboKey.js"></script>;
onTrigger(callback, preventDefault)欢迎提交 Issue 和 Pull Request!
MIT License - 可自由使用和修改