ComboKeys

ComboKeys 2.0

一个现代化、类型安全的 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();

📚 API 文档

构造函数

// 方式一:数组 + 选项对象
new ComboKeys(keys, options);

// 方式二:配置对象
new ComboKeys(config);

参数说明:

核心方法

keys(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 采用了现代化的面向对象设计,融合了多种设计模式:

1. 事件驱动架构

2. 状态机模式

3. 建造者模式

4. 策略模式

两种工作模式

🔗 组合键模式(同时按住)

当检测到修饰键(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);
}

内存管理优化

API 设计原则

1. 直观性

// ❌ 旧版本:方法名不够直观
combo.do(callback).on();

// ✅ 新版本:语义明确
combo.onTrigger(callback).start();

2. 一致性

// 所有配置方法都返回 this,支持链式调用
combo.keys([...]).timeout(1000).onTrigger(...).start();

3. 容错性

// 重复调用 start() 不会出错
combo.start().start(); // 第二次调用会输出警告但不抛异常

4. 可扩展性

// 静态常量便于扩展
static KEY_SYMBOLS = { keydown: '+', keyup: '-' };
static DEFAULT_OPTIONS = { /* ... */ };

🎯 使用场景

游戏开发

// 格斗游戏招式系统
const hadoken = new ComboKeys(["ArrowDown", "ArrowRight", "KeyP"])
  .timeout(500)
  .onTrigger(() => this.castFireball(), false) // 允许方向键滚动页面
  .start();

Web 应用快捷键

// 编辑器快捷键(通常需要阻止默认行为)
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();

🎨 最佳实践

1. 错误处理

try {
  const combo = new ComboKeys(["ControlLeft", "KeyC"]).onTrigger(() => console.log("复制")).start();
} catch (error) {
  console.error("组合键创建失败:", error.message);
}

2. 默认行为控制

// 完全阻止默认行为(默认)
combo.onTrigger(callback);

// 显式阻止默认行为
combo.onTrigger(callback, true);

// 允许默认行为
combo.onTrigger(callback, false);

3. 资源清理

// 页面卸载时清理资源
window.addEventListener("beforeunload", () => {
  comboInstances.forEach((combo) => combo.stop(true));
});

4. 状态监控

// 定期检查组合键状态
setInterval(() => {
  const status = combo.getStatus();
  if (status.progress !== "0/4") {
    console.log(`进度: ${status.progress}`);
  }
}, 1000);

5. 条件控制

// 根据应用状态控制监听
if (isGameMode) {
  gameCombo.start();
} else {
  gameCombo.stop();
}

🔧 兼容性

特性 支持情况
浏览器 Chrome 51+, Firefox 54+, Safari 10.1+, Edge 79+
Node.js 不支持(需要 DOM 环境)
TypeScript 兼容(提供类型推导)
ES 模块 支持
CommonJS 支持

技术依赖:

📦 安装与导入

// ES6 模块
import ComboKeys from "./ComboKey.js";

// CommonJS
const ComboKeys = require("./ComboKey.js");

// 直接引入
<script src="ComboKey.js"></script>;

🚀 版本更新

v2.0.0 (当前版本)

v1.0.0 (旧版本)

🤝 贡献指南

欢迎提交 Issue 和 Pull Request!

📄 许可证

MIT License - 可自由使用和修改