我一直在制作一个在线钢琴,使用键盘作为输入.有时,当你按下一个键时,它会记录两个事件而不是一个.
问题是,我试着用e.repeat
(其中e
是键盘事件)只注册第一个按键事件.
你可以try 在这个临时链接上使用它:https://virtual-piano-demo.netlify.app/
一般来说,我对JavaScript和web开发相对较新,因此欢迎对我的代码提出任何建议.
if (!e.repeat && isValidInput(e.key)) {
let pitch = keysMap.get(e.key);
playNote(pitch);
document.getElementById(pitch).classList.add("key-bkg-color"); // change color of key
}
这是相关代码.
let notes = document.getElementsByClassName("note");
let soften = document.getElementById("soften");
let sustain = document.getElementById("sustain");
let piano = document.getElementById("piano");
let context = new (window.AudioContext || window.webkitAudioContext)();
let keysMap = new Map([
['q', "C3"],
['2', "Db3"],
['w', "D3"],
['3', "Eb3"],
['e', "E3"],
['r', "F3"],
['5', "Gb3"],
['t', "G3"],
['6', "Ab3"],
['y', "A3"],
['7', "Bb3"],
['u', "B3"],
['i', "C4"],
['9', "Db4"],
['o', "D4"],
['0', "Eb4"],
['p', "E4"],
['[', "F4"],
['=', "Gb4"],
[']', "G4"],
['a', "Ab4"],
['z', "A4"],
['s', "Bb4"],
['x', "B4"],
['c', "C5"],
['f', "Db5"],
['v', "D5"],
['g', "Eb5"],
['b', "E5"],
['n', "F5"],
['j', "Gb5"],
['m', "G5"],
['k', "Ab5"],
[',', "A5"],
['l', "Bb5"],
['.', "B5"],
['/', "C6"],
]);
// load all audio files when page loads so that when the user presses keys the sounds start on time
// store buffers in array to access piano sounds when user presses a key
let buffers = [];
window.addEventListener("load", function() {
for (let i = 0; i < notes.length; ++i) {
let request = new XMLHttpRequest();
request.open("GET", "./audio/" + notes[i].id + ".mp3");
request.responseType = "arraybuffer";
request.onload = function() {
let undecodedAudio = request.response;
context.decodeAudioData(undecodedAudio, (data) => buffers[notes[i].id] = data)
}
request.send();
}
})
function isValidInput(input) {
return keysMap.has(input) === true;
}
function playNote(pitch) {
let playSound = context.createBufferSource();
let gainNode = context.createGain();
playSound.buffer = buffers[pitch];
if (soften.checked === true) {
gainNode.gain.setValueAtTime(0.6, context.currentTime);
gainNode.gain.exponentialRampToValueAtTime(1.05, context.currentTime + 0.35);
}
else {
gainNode.gain.setValueAtTime(1.5, context.currentTime);
}
playSound.connect(gainNode);
gainNode.connect(context.destination);
playSound.start(context.currentTime);
if (sustain.checked === false) {
gainNode.gain.exponentialRampToValueAtTime(0.001, context.currentTime + 3);
}
}
// Keyboard Input
document.addEventListener("keydown", function(e) {
// the pressed key is used for input in the piano -> play note
// !e.repeat makes sure that only the first keydown event when holding down on a certain key is taken into account
if (!e.repeat && isValidInput(e.key)) {
let pitch = keysMap.get(e.key);
playNote(pitch);
document.getElementById(pitch).classList.add("key-bkg-color"); // change color of key
}
})
document.addEventListener("keyup", function(e) {
let pitch = keysMap.get(e.key);
document.getElementById(pitch).classList.remove("key-bkg-color"); // change color of key
})