模拟钢琴时,如何阻止音频在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
相关产品推荐
相关产品推荐

