You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

监听键盘事件(keyup/keydown):Mac OS浏览器中条件语句为何失效?

问题描述

开发了一款开源音乐应用,核心功能是按下键盘按键播放对应预定义音符。通过监听keydown事件,在处理函数中用if (freq && !runningOscs[freq])判断,借助存储运行中振荡器的runningOscs对象(格式{440: osc})避免按住按键时重复播放音符。

但在Mac OS全系列浏览器中,该条件判断失效,按住按键会连续重复播放音符。已精简最小复现示例并通过BrowserStack测试,所有Mac OS+浏览器组合均存在此问题。

尝试添加e.repeat判断拦截重复事件,但在Mac OS Ventura的Chrome v110中,按住按键时e.repeat始终返回false,无法解决问题。

解决方案

放弃依赖e.repeat,改为手动维护按键状态追踪对象,直接记录哪些按键处于按下状态,从根源避免重复触发播放逻辑。

修改后的完整代码如下:

console.log("Yo! There! Mac O'");

// 实例化音频上下文
const audioCTX = new AudioContext();
const freq = 440; // 振荡器频率
let runningOscs = {}; // 存储运行中的振荡器
let pressedKeys = {}; // 新增:追踪已按下的按键

function playNote(freq) {
  const osc = audioCTX.createOscillator();
  osc.frequency.value = freq; // 修正原代码中频率不匹配的问题
  osc.type = "sine";

  const vol = audioCTX.createGain();
  vol.gain.value = 1;

  runningOscs[freq] = osc;
  console.log(runningOscs);

  runningOscs[freq].connect(vol).connect(audioCTX.destination);
  runningOscs[freq].start();
}

// 事件监听
window.addEventListener("keydown", keyDownHandler, false);
window.addEventListener("keyup", keyupHandler, false);

function keyDownHandler(e) {
  // 检查当前按键是否已被记录为按下状态
  if (pressedKeys[e.key]) return;
  
  // 标记按键为已按下
  pressedKeys[e.key] = true;
  
  if (freq && !runningOscs[freq]) {
    playNote(freq);
    console.log(runningOscs);
  }
}

function keyupHandler(e) {
  console.log("key up!");
  // 清除按键的按下状态
  delete pressedKeys[e.key];
  
  if (freq && runningOscs[freq]) {
    runningOscs[freq].stop();
    delete runningOscs[freq];
  }
}
<!DOCTYPE html>
<p>press a key to play a note</p>
<p>holding the key down</p>
<p>should play only one instance</p>
关键改动说明
  1. 新增pressedKeys对象:专门记录当前处于按下状态的按键,键名为键盘事件的e.key值(也可根据需求改用e.code实现更精准的按键匹配)。
  2. 修改keydown逻辑:触发时先检查pressedKeys中是否已存在当前按键,若存在则直接返回,避免重复执行播放;若不存在则标记为已按下,再执行原有的音符播放判断。
  3. 修正频率不匹配问题:原代码中playNote函数硬写了osc.frequency.value = 220,和传入的freq=440不一致,现在改为使用传入的freq参数。

这种方式不依赖浏览器的e.repeat属性,完全通过本地状态控制,能在所有平台的浏览器中稳定生效,解决Mac OS上的重复播放问题。

内容的提问来源于stack exchange,提问作者Fishbite

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 20:27:05