使用 tone.js 制作钢琴!
钢琴
钢琴
这就是我们要构建的最终产品!您可以点击它,或者在键盘上输入匹配的字母。
什么是 Tone.js?
Tone.js 是一个非常流行的 Web Audio API 库,其GitHub 仓库中拥有超过 8000 个 star 。在 Web Audio API 出现之前,浏览器必须使用音频文件来播放声音和音乐。这不仅增大了应用程序的体积,而且修改声音意味着每次都需要引入不同的音频文件。那么,Web Audio API 能为我们做些什么呢?
Web Audio API 提供了一个强大且多功能的系统来控制 Web 上的音频,允许开发人员选择音频源、为音频添加效果、创建音频可视化、应用空间效果(例如平移)等等。
出处: https: //developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API
它的一个非常强大的功能是,现在只需 JavaScript 即可生成数字声音,无需使用音频文件!只需掌握一些音乐概念,例如振荡器和频率,我们就能创建各种符合我们需求的音频。使用纯 Web Audio API 会有些困难,因为它涉及一些底层概念,所以我们将在项目中使用 Tone.js,它可以抽象出底层方法。
HTML
<ul id="piano">
<li data-note="C4" class="key">
<div data-note="C#4" class="black-key">R</div>
D
</li>
<li data-note="D4" class="key">
<div data-note="D#4" class="black-key">T</div>
F
</li>
<li data-note="E4" class="key">
G
</li>
<li data-note="F4" class="key">
<div data-note="F#4" class="black-key">U</div>
H
</li>
<li data-note="G4" class="key">
<div data-note="G#4" class="black-key">I</div>
J
</li>
<li data-note="A4" class="key">
<div data-note="A#4" class="black-key">O</div>
K
</li>
<li data-note="B4" class="key">
L
</li>
</ul>
我们的标记相当简单。白键用“key”类表示,黑键用“black-key”类表示。注意,在HTML层次结构中,黑键被包裹在白键内部,以便相对定位。每个键还具有 data-note 属性,并带有相应的音符。
CSS
@import url('https://fonts.googleapis.com/css?family=Roboto:400,700&display=swap');
body {
font-family: 'Roboto', sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
ul {
list-style: none;
display: flex;
}
ul .key {
position: relative;
width: 60px;
height: 180px;
border: 1px solid black;
border-right: none;
background: #fffff0;
border-radius: 5px;
box-shadow: 0px 3px 5px #666;
cursor: pointer;
display: flex;
justify-content: center;
align-items: flex-end;
padding-bottom: 10px;
font-weight: bold;
}
ul .key:last-child {
border-right: 1px solid black;
}
ul .black-key {
position: absolute;
top: -1px;
left: 37.5px;
width: 45px;
height: 120px;
background: black;
border-radius: 5px;
box-shadow: 0px 3px 5px #666;
z-index: 999;
display: flex;
justify-content: center;
align-items: flex-end;
padding-bottom: 10px;
color: white;
}
.key 为我们的白键设置样式。它用于align-items: flex-end
将字母放置在键的底部。
JavaScript
// Tone.Synth is a basic synthesizer with a single oscillator
const synth = new Tone.Synth();
// Set the tone to sine
synth.oscillator.type = "sine";
// connect it to the master output (your speakers)
synth.toMaster();
const piano = document.getElementById("piano");
piano.addEventListener("mousedown", e => {
// fires off a note continously until trigger is released
synth.triggerAttack(e.target.dataset.note);
});
piano.addEventListener("mouseup", e => {
// stops the trigger
synth.triggerRelease();
});
// handles keyboard events
document.addEventListener("keydown", e => {
// e object has the key property to tell which key was pressed
switch (e.key) {
case "d":
return synth.triggerAttack("C4");
case "r":
return synth.triggerAttack("C#4");
case "f":
return synth.triggerAttack("D4");
case "t":
return synth.triggerAttack("D#4");
case "g":
return synth.triggerAttack("E4");
case "h":
return synth.triggerAttack("F4");
case "u":
return synth.triggerAttack("F#4");
case "j":
return synth.triggerAttack("G4");
case "i":
return synth.triggerAttack("G#4");
case "k":
return synth.triggerAttack("A4");
case "o":
return synth.triggerAttack("A#4");
case "l":
return synth.triggerAttack("B4");
default:
return;
}
});
// when the key is released, audio is released as well
document.addEventListener("keyup", e => {
switch (e.key) {
case "d":
case "r":
case "f":
case "t":
case "g":
case "h":
case "u":
case "j":
case "i":
case "k":
case "o":
case "l":
synth.triggerRelease();
}
});
让我们分解一下。前三行使用了 Tone.js 提供的方法并设置了声音。然后,我们将事件监听器附加到钢琴 div 上,它会使用事件冒泡来识别在监听到点击事件后被定位到的元素。我们获取元素的 data-note 属性来播放其声音。
我们无法对键盘事件做同样的事情,因为键盘按下时生成的事件对象与鼠标点击生成的事件对象不同。这就是为什么我们必须手动将键盘字母映射到相应的音符。
结局
希望这个演示易于理解,并能克服你探索 Web Audio API 的恐惧!如有任何疑问或想法,欢迎在评论区留言!感谢阅读这篇博客!😆😊😃
鏂囩珷鏉ユ簮锛�https://dev.to/shimphillip/building-a-piano-with-tone-js-5c2f