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

模拟钢琴时,如何阻止音频在onmouseup事件触发时重复播放?

解决钢琴模拟中长按琴键松开时重复播放音频的问题

问题核心并非事件传播,而是对Audio API的行为逻辑处理有误:

当延音开启(isSustained为真)时,keyReturn函数中未暂停音频却直接设置currentTime = 0——此时音频正处于播放状态,修改currentTime会让它立刻跳转到开头并继续播放,相当于触发了第二次播放,这就是松开鼠标时音频重复播放的原因。

修复方案

1. 调整keyReturn函数逻辑

仅在关闭延音、需要暂停音频时重置currentTime;延音开启时,让音频自然播放完毕:

2. 优化keyPlay函数

每次播放前先重置currentTime,避免重复点击或长按导致的音频叠加问题,同时保证每次按键都从音频起始位置播放。

修复后的完整代码:

const keysObj = {
  'c-key': new Audio(dir + 'key08-middleC.mp3'), 
  'd-key': new Audio(dir + 'key10.mp3'), 
  // 其他琴键音频...
}

let keyPlay = (key) => {
  const audio = keysObj[key.target.id];
  audio.currentTime = 0; // 播放前重置到起始位置
  audio.play();
}

let keyReturn = (key) => {
  const isSustained = document.querySelector("input[name='sustain']:checked");
  const audio = keysObj[key.target.id];

  if (!isSustained) {
    audio.pause();
    audio.currentTime = 0; // 仅暂停时重置,避免播放中跳转
  }
}

let keyPress = (note) => {
  note.onmousedown = keyPlay;
  note.onmouseup = keyReturn;
}

补充说明

  • 原事件绑定逻辑没有传播问题,无需调整事件绑定方式。
  • 优化后的keyPlay逻辑更贴合真实钢琴的按键反馈:无论之前音频是否在播放,每次按键都从开头触发播放。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 03:17:08