Files
kiss-translator/src/libs/shortcut.js

115 lines
2.9 KiB
JavaScript
Raw Normal View History

2023-09-07 23:47:24 +08:00
import { isSameSet } from "./utils";
/**
* 键盘快捷键监听器
* @param {(pressedKeys: Set<string>, event: KeyboardEvent) => void} onKeyDown - Keydown 回调
* @param {(pressedKeys: Set<string>, event: KeyboardEvent) => void} onKeyUp - Keyup 回调
* @param {EventTarget} target - 监听的目标元素
* @returns {() => void} - 用于注销监听的函数
2023-09-07 23:47:24 +08:00
*/
export const shortcutListener = (
onKeyDown = () => {},
onKeyUp = () => {},
target = document
) => {
const pressedKeys = new Set();
2023-09-08 13:53:33 +08:00
const handleKeyDown = (e) => {
2025-10-11 11:19:33 +08:00
if (!e.code) {
return;
}
if (pressedKeys.has(e.code)) return;
pressedKeys.add(e.code);
onKeyDown(new Set(pressedKeys), e);
2023-09-07 23:47:24 +08:00
};
const handleKeyUp = (e) => {
2025-10-11 11:19:33 +08:00
if (!e.code) {
return;
}
// onKeyUp 应该在 key 从集合中移除前触发,以便判断组合键
onKeyUp(new Set(pressedKeys), e);
pressedKeys.delete(e.code);
2023-09-07 23:47:24 +08:00
};
target.addEventListener("keydown", handleKeyDown);
target.addEventListener("keyup", handleKeyUp);
2023-09-07 23:47:24 +08:00
return () => {
target.removeEventListener("keydown", handleKeyDown);
target.removeEventListener("keyup", handleKeyUp);
pressedKeys.clear();
2023-09-07 23:47:24 +08:00
};
};
/**
* 注册键盘快捷键
* @param {string[]} targetKeys - 目标快捷键数组
* @param {() => void} fn - 匹配成功后执行的回调
* @param {EventTarget} target - 监听目标
* @returns {() => void} - 注销函数
2023-09-07 23:47:24 +08:00
*/
2023-09-09 15:26:05 +08:00
export const shortcutRegister = (targetKeys = [], fn, target = document) => {
if (targetKeys.length === 0) return () => {};
const targetKeySet = new Set(targetKeys);
const onKeyDown = (pressedKeys, event) => {
2025-09-25 00:21:51 +08:00
if (isSameSet(targetKeySet, pressedKeys)) {
event.preventDefault();
event.stopPropagation();
2023-09-07 23:47:24 +08:00
fn();
}
};
const onKeyUp = () => {};
return shortcutListener(onKeyDown, onKeyUp, target);
2023-09-07 23:47:24 +08:00
};
2023-09-13 15:53:40 +08:00
/**
* 高阶函数为目标函数增加计次和超时重置功能
* @param {() => void} fn - 需要被包装的函数
* @param {number} step - 需要触发的次数
* @param {number} timeout - 超时毫秒数
* @returns {() => void} - 包装后的新函数
2023-09-13 15:53:40 +08:00
*/
const withStepCounter = (fn, step, timeout) => {
2023-09-13 15:53:40 +08:00
let count = 0;
let timer = null;
return () => {
2023-09-13 18:02:51 +08:00
timer && clearTimeout(timer);
timer = setTimeout(() => {
count = 0;
}, timeout);
count++;
if (count === step) {
count = 0;
clearTimeout(timer);
fn();
2023-09-13 15:53:40 +08:00
}
};
};
/**
* 注册连续快捷键
* @param {string[]} targetKeys - 目标快捷键数组
* @param {() => void} fn - 成功回调
* @param {number} step - 连续触发次数
* @param {number} timeout - 每次触发的间隔超时
* @param {EventTarget} target - 监听目标
* @returns {() => void} - 注销函数
*/
export const stepShortcutRegister = (
targetKeys = [],
fn,
step = 2,
timeout = 500,
target = document
) => {
const steppedFn = withStepCounter(fn, step, timeout);
return shortcutRegister(targetKeys, steppedFn, target);
2023-09-13 15:53:40 +08:00
};