【前端实战】从零构建在线钢琴 — Vue 3 + Tone.js 实现教程前言
·
项目简介
大家好,我是唐朝,来自汤阴县豫唐网络科技有限公司。今天给大家分享我们团队的一个作品——豫唐·星空钢琴。
在线体验:https://www.ytecn.com/lab/piano
源码地址:https://gitee.com/ytecnsong/piano

目录
项目背景
钢琴学习门槛高、费用高,对初学者很不友好。我们的目标是:
-
零门槛:浏览器即用,无需安装
-
趣味化:星空主题,边看边学
-
可扩展:支持自定义曲目
技术选型
|
技术栈 |
用途 |
|---|---|
|
Vue 3 (Composition API) |
界面与状态 |
|
Vite |
快速构建 |
|
Tone.js |
Web Audio 封装 |
|
localStorage |
数据存储 |
为什么选 Tone.js?
原生 Web Audio API 太复杂,Tone.js 封装了 polyphony(多音)、scheduling(调度)、effects(效果)等功能,代码量减少约 70%。
核心代码实现
1. 音频引擎封装
import * as Tone from 'tone'
export const audioEngine = {
synth: null,
async init() {
await Tone.start() // 必须在用户交互后调用!
this.synth = new Tone.PolySynth(Tone.Synth).toDestination()
this.synth.volume.value = -6
},
playNote(note, duration = '8n') {
if (this.synth) {
this.synth.triggerAttackRelease(note, duration)
}
}
}
2. 键盘映射与事件监听
const KEY_MAP = {
'z': 'C3', 'x': 'D3', 'c': 'E3', 'v': 'F3', 'b': 'G3', 'n': 'A3', 'm': 'B3',
'a': 'C4', 's': 'D4', 'd': 'E4', 'f': 'F4', 'g': 'G4', 'h': 'A4', 'j': 'B4',
'q': 'C5', 'w': 'D5', 'e': 'E5', 'r': 'F5', 't': 'G5', 'y': 'A5', 'u': 'B5'
}
window.addEventListener('keydown', (e) => {
if (activeKeys.has(e.key)) return
activeKeys.add(e.key)
const note = KEY_MAP[e.key.toLowerCase()]
if (note) audioEngine.playNote(note)
})
3. 曲目播放与高亮
function playSong(song, onNote) {
let index = 0
const interval = setInterval(() => {
if (index >= song.notes.length) {
clearInterval(interval)
return
}
const { note } = song.notes[index]
audioEngine.playNote(note)
onNote(index) // 高亮当前键
index++
}, 500)
}
4. 导入导出功能
// 导出为 JSON 文件
function exportSong(song) {
const blob = new Blob([JSON.stringify(song, null, 2)], { type: 'application/json' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.download = `${song.name}.json`
a.href = url
a.click()
URL.revokeObjectURL(url)
}
// 导入文件
function importSong(file) {
const reader = new FileReader()
reader.onload = (e) => {
const data = JSON.parse(e.target.result)
songManager.addSong(data)
}
reader.readAsText(file)
}
项目结构
yutang-piano/
├── index.html
├── package.json
├── vite.config.js
└── src/
├── main.js
├── App.vue
├── audio-engine.js
├── song-manager.js
└── components/
├── SplashScreen.vue
├── PianoKeyboard.vue
├── SongPanel.vue
├── SongEditor.vue
└── VolumeControl.vue
注意事项与踩坑
-
浏览器自动播放策略:Tone.start() 必须用户触发(如点击)后调用
-
localStorage 大小限制:约 5MB,别存太多大曲目
-
移动端键盘问题:手机平板建议只做触摸弹奏,不支持键盘输入
-
Tone.js 初始化时机:先点页面,再初始化音频引擎
总结与展望
我们实现了一个轻量级的在线钢琴学习平台。未来方向:
-
MIDI 输入支持
-
多音色切换
-
录音回放
-
云存储同步
相关资源
-
关于我们:汤阴县豫唐网络科技有限公司
更多推荐
所有评论(0)