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

JS鼓机按钮首次点击无效,二次点击才响应的问题解决求助

鼓机首次点击无响应问题解决方案

问题描述

我正在用JavaScript开发一款鼓机,目前遇到的问题是所有按钮首次点击时无响应,必须点击第二次才能正常触发音频播放与显示更新。猜测可能是函数初始化阶段未正确绑定点击事件,请教如何修改现有代码解决该问题?

问题原因

  1. 同时使用了HTML内联onClick属性和JS的addEventListener绑定点击事件,两种事件触发顺序导致首次点击时音频播放与显示更新不同步,且浏览器自动播放策略可能拦截未预加载的音频首次播放请求。
  2. 音频元素未设置预加载,首次点击时资源尚未就绪,导致播放失败。

修改方案

  1. 移除按钮上的内联onClick属性,统一通过JS绑定事件,避免逻辑冲突
  2. 给所有<audio>标签添加preload="auto",提前加载音频资源
  3. 合并音频播放与显示更新逻辑到同一处理函数,保证操作同步
  4. 复用处理函数优化键盘事件逻辑,减少代码冗余

修改后的完整代码

HTML

<div id="drum-machine">
  <div class="result" id="display">
    <p></p>
  </div>

  <button class="drum-pad" id="0" name="Heater 1">
    <audio class="clip" id="Q" src="https://s3.amazonaws.com/freecodecamp/drums/Heater-1.mp3" preload="auto">
    </audio>
    Q
  </button>

  <button class="drum-pad" id="1" name="Heater 2">
    <audio class="clip" id="W" src="https://s3.amazonaws.com/freecodecamp/drums/Heater-2.mp3" preload="auto">
    </audio>
    W
  </button>

  <button class="drum-pad" id="2" name="Heater 3">
    <audio class="clip" id="E" src="https://s3.amazonaws.com/freecodecamp/drums/Heater-3.mp3" preload="auto">
    </audio>
    E
  </button>

  <button class="drum-pad" id="3" name="Heater 4">
    <audio class="clip" id="A" src="https://s3.amazonaws.com/freecodecamp/drums/Heater-4_1.mp3" preload="auto">
    </audio>
    A
  </button>

  <button class="drum-pad" id="4" name="Heater 6">
    <audio class="clip" id="S" src="https://s3.amazonaws.com/freecodecamp/drums/Heater-6.mp3" preload="auto">
    </audio>
    S
  </button>

  <button class="drum-pad" id="5" name="Open HH">
    <audio class="clip" id="D" src="https://s3.amazonaws.com/freecodecamp/drums/Dsc_Oh.mp3" preload="auto">
    </audio>
    D
  </button>

  <button class="drum-pad" id="6" name="Kick n' Hat">
    <audio class="clip" id="Z" src="https://s3.amazonaws.com/freecodecamp/drums/Kick_n_Hat.mp3" preload="auto">
    </audio>
    Z
  </button>

  <button class="drum-pad" id="7" name="Kick">
    <audio class="clip" id="X" src="https://s3.amazonaws.com/freecodecamp/drums/RP4_KICK_1.mp3" preload="auto">
    </audio>
    X
  </button>

  <button class="drum-pad" id="8" name="Closed HH">
    <audio class="clip" id="C" src="https://s3.amazonaws.com/freecodecamp/drums/Cev_H2.mp3" preload="auto">
    </audio>
    C
  </button>
</div>

CSS

body {
  display: flex;
  justify-content: center;
}

#drum-machine {
  margin: 0 auto;
  display: flex;
  flex-flow: row wrap;
  justify-content: center;
}

#display {
  width: 200px;
  height: 60px;
  border: solid black;
}

JavaScript

// 通用处理函数:播放音频并更新显示
function handleDrumTrigger(audioElement, displayText) {
  // 重置音频播放位置,避免重复点击时无法重新播放
  audioElement.currentTime = 0;
  audioElement.play();
  document.getElementsByClassName('result')[0].innerHTML = displayText;
}

// 绑定按钮点击事件
const drumPads = document.getElementsByClassName('drum-pad');
for (let i = 0; i < drumPads.length; i++) {
  drumPads[i].addEventListener('click', function(e) {
    const audio = this.querySelector('.clip');
    const displayText = this.name;
    handleDrumTrigger(audio, displayText);
  });
}

// 键盘事件处理
const keyCodes = [
  { code: 81, name: "Heater 1", audioId: "Q" },
  { code: 87, name: "Heater 2", audioId: "W" },
  { code: 69, name: "Heater 3", audioId: "E" },
  { code: 65, name: "Heater 4", audioId: "A" },
  { code: 83, name: "Heater 6", audioId: "S" },
  { code: 68, name: "Open HH", audioId: "D" },
  { code: 90, name: "Kick n' Hat", audioId: "Z" },
  { code: 88, name: "Kick", audioId: "X" },
  { code: 67, name: "Closed HH", audioId: "C" }
];

document.addEventListener('keydown', function(e) {
  const keyData = keyCodes.find(item => item.code === e.keyCode);
  if (keyData) {
    const audio = document.getElementById(keyData.audioId);
    handleDrumTrigger(audio, keyData.name);
  }
});

额外说明

  • 添加audio.currentTime = 0是为了让重复点击时音频可以重新从头播放,避免音频还在播放时点击无反应
  • 使用let替代var在循环中绑定事件,避免闭包导致的索引问题
  • 键盘事件改用find方法查找对应按键数据,代码更简洁高效

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 16:15:26