如何在文本框外正确捕获CTRL+Z、CTRL+Y组合键?
解决Ctrl+Z/Y按键组合捕获问题
核心问题:keypress事件的局限性
keypress事件仅针对可打印字符输入设计,对于Ctrl+Z、Ctrl+Y这类涉及控制键的组合键,它无法正确返回对应按键值(会出现空字符或异常值),这是你当前问题的根本原因。
解决方案:改用keydown/keyup事件
keydown/keyup事件能完整捕获所有按键信息,包括控制键状态和具体按键值。以下是修改后的代码:
let history = [] let step let canvas = new fabric.Canvas("canvas", { width: window.innerWidth, height: window.innerHeight, backgroundColor: "transparent", isDrawingMode: true }); history.push(JSON.stringify(canvas)); step = 0 canvas.on("object:added", () => { if (step !== history.length-1) history = history.slice(0, step + 1); history.push(JSON.stringify(canvas)); step++; console.log(step); }); document.addEventListener("keydown", event => { // 阻止浏览器默认的撤销/重做行为,避免与自定义逻辑冲突 if (event.ctrlKey && (event.key === "z" || event.key === "y")) { event.preventDefault(); } // 处理撤销(Ctrl+Z) if (event.ctrlKey && event.key === "z" && step > 0) { step--; const content = history[step]; canvas.loadFromJSON(content, () => canvas.renderAll()); console.log("撤销后步骤:", step); } // 处理重做(Ctrl+Y) if (event.ctrlKey && event.key === "y" && step < history.length - 1) { step++; const content = history[step]; canvas.loadFromJSON(content, () => canvas.renderAll()); console.log("重做后步骤:", step); } });
关键优化点说明
- 事件类型切换:替换
keypress为keydown,确保能准确捕获Ctrl+Z/Y的按键组合信息。 - 阻止默认行为:调用
event.preventDefault()避免浏览器自带的撤销/重做操作干扰自定义逻辑。 - 明确按键判断:直接通过
event.key === "z"或"y"匹配按键,替代原有的空字符模糊判断。 - 边界校验:给撤销/重做添加
step的边界限制(如step > 0、step < history.length -1),防止数组越界。
可选:限制输入框外触发
如果需要仅在输入框/文本域外触发该逻辑,可在事件处理中添加目标元素判断:
document.addEventListener("keydown", event => { const inputTags = ["INPUT", "TEXTAREA"]; // 若触发源是输入类元素,直接跳过 if (inputTags.includes(event.target.tagName)) return; // 后续撤销/重做逻辑... });
关于step异常触发的补充建议
step数值超出预期的问题,大概率和object:added事件重复触发有关。可检查Fabric.js的isDrawingMode模式下,是否每次绘制路径都会多次触发该事件,或添加防抖处理避免重复推入历史记录。
内容的提问来源于stack exchange,提问作者Konstei
相关产品推荐
相关产品推荐

