酷代码 AI
菜单
全部AI  /  热门  /  AI写代码神器
服务商

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>在线钢琴</title> <style> body { display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; background-color: #f0f0f0; } .piano-container { width: 1000px; height: 600px; background

我注意到你的代码在生成黑键部分没有完成,我来帮你完善这个在线钢琴的实现。以下是完整的JavaScript代码部分: ```javascript // 生成黑键 const blackKeyPositions = [1, 3, 4, 6, 8]; // 每个八度内黑键的位置(相对于白键索引) for (let octave = 0; octave < octaves; octave++) { blackKeyPositions.forEach(pos => { const key = document.createElement('div'); key.className = 'black-key'; key.dataset.note = octave * 12 + pos + 24; // 计算MIDI音符编号 key.addEventListener('mousedown', handleKeyDown); key.addEventListener('mouseup', handleKeyUp); key.addEventListener('touchstart', handleTouchStart); key.addEventListener('touchend', handleTouchEnd); keysRow.appendChild(key); }); } // 事件处理函数 function handleKeyDown(e) { const key = e.currentTarget; key.classList.add('active'); playNote(parseInt(key.dataset.note)); if (isRecording) { recording.push({ note: parseInt(key.dataset.note), time: context.currentTime, type: 'start' }); } currentNote = parseInt(key.dataset.note); } function handleKeyUp(e) { const key = e.currentTarget; key.classList.remove('active'); if (isRecording) { recording.push({ note: parseInt(key.dataset.note), time: context.currentTime, type: 'stop' }); } currentNote = null; } function handleTouchStart(e) { e.preventDefault(); handleKeyDown(e); } function handleTouchEnd(e) { e.preventDefault(); handleKeyUp(e); } // 播放音符 function playNote(note) { const oscillator = context.createOscillator(); const gainNode = context.createGain(); oscillator.type = 'sine'; oscillator.frequency.value = 440 * Math.pow(2, (note - 69) / 12); // 转换为频率 gainNode.gain.value = 0.3; oscillator.connect(gainNode); gainNode.connect(context.destination); oscillator.start(); gainNode.gain.exponentialRampToValueAtTime(0.001, context.currentTime + 0.5); oscillator.stop(context.currentTime + 0.5); } // 控制按钮事件 document.getElementById('recordBtn').addEventListener('click', () => { isRecording = !isRecording; const btn = document.getElementById('recordBtn'); btn.textContent = isRecording ? '停止录音' : '开始录音'; if (isRecording) { recording = []; } }); document.getElementById('playBtn').addEventListener('click', () => { if (recording.length === 0) return; const startTime = context.currentTime; recording.forEach(event => { const time = event.time - recording[0].time; if (event.type === 'start') { setTimeout(() => { playNote(event.note); }, time * 1000); } }); }); document.getElementById('clearBtn').addEventListener('click', () => { recording = []; }); ``` 额外需要注意的逻辑点: 1. MIDI音符编号系统需要正确映射到钢琴键位,起始音符24对应C2。 2. 黑键的位置计算需要考虑每个八度内的相对位置和跨八度的偏移。 3. 录音功能需要精确记录按键按下和释放的时间点,以便准确回放。 [2025-04-19 13:57:24 | AI写代码神器 | 780点数解答]

相关提问