前言
html5让我们拥有强大的模仿能力,下面让我们通过html5来写一个音乐键盘,实现在线打击乐。
正文
html
整体布局:
- 通过div来实现键盘盒子容器
- 通过audio标签元素来存放音频
- div中的
data-key属性定义了与每个键关联的键盘按键代码,用于后续js中识别哪个键被按下 - audio中的
data-key属性匹配了前面div元素中的data-key值,用于连接按键事件和音频播放
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML5打击乐</title>
<link rel="stylesheet" href="./common.css">
</head>
<body>
<!-- .keys>(.key>div+span.sound)*9 -->
<div class="keys">
<div class="key" data-key = '65'>
<div>A</div>
<span class="sound">clap</span>
</div>
<div class="key" data-key = '83'>
<div>S</div>
<span class="sound">hihat</span>
</div>
<div class="key" data-key = '68'>
<div>D</div>
<span class="sound">kick</span>
</div>
<div class="key" data-key = '70'>
<div>F</div>
<span class="sound">openhat</span>
</div>
<div class="key" data-key = '71'>
<div>G</div>
<span class="sound">boom</span>
</div>
<div class="key" data-key = '72'>
<div>H</div>
<span class="sound">ride</span>
</div>
<div class="key" data-key = '74'>
<div>J</div>
<span class="sound">snare</span>
</div>
<div class="key" data-key = '75'>
<div>K</div>
<span class="sound">tom</span>
</div>
<div class="key" data-key = '76'>
<div>L</div>
<span class="sound">tink</span>
</div>
</div>
<!-- audio[src="./sounds/.wav"][data-key=""]*9 -->
<audio src="./sounds/clap.wav" data-key="65"></audio>
<audio src="./sounds/hihat.wav" data-key="83"></audio>
<audio src="./sounds/kick.wav" data-key="68"></audio>
<audio src="./sounds/openhat.wav" data-key="70"></audio>
<audio src="./sounds/boom.wav" data-key="71"></audio>
<audio src="./sounds/ride.wav" data-key="72"></audio>
<audio src="./sounds/snare.wav" data-key="74"></audio>
<audio src="./sounds/tom.wav" data-key="75"></audio>
<audio src="./sounds/tink.wav" data-key="76"></audio>
<script src="./common.js"></script>
</body>
</html>
css
* {
margin: 0;
padding: 0;
}
html {
font-size: 10px;
background: url("./bg.jpg") bottom center no-repeat;
background-size: cover;
}
body,
html {
font-family: sans-serif;
}
body {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.keys {
display: flex;
}
.keys .key {
margin: 1rem;
border: 0.4rem solid #000;
border-radius: 0.5rem;
font-size: 1.5rem;
padding: 1rem 0.5rem;
width: 10rem;
text-align: center;
color: #fff;
background: rgba(0,0,0,0.4);
text-shadow: 0 0 0.5rem #000;
transition: all 0.07s ease;
}
.keys .key div {
font-size: 4rem;
}
.keys .key .sound {
font-size: 1.2rem;
letter-spacing: 0.1rem;
color: #ffc600;
}
.keys .key.playing {
transform: scale(1.1);
border-color: #ffc600;
box-shadow: 0 0 1rem #ffc600;
}
js
function playSound(e) {
// console.log(e.keyCode, '////');
let keyCode = e.keyCode;
const key = document.querySelector(`.key[data-key="${keyCode}"]`);
const audio = document.querySelector(`audio[data-key="${keyCode}"]`);
// console.log(audio);
if(!key) return;
key.classList.add('playing');
audio.play();
// 65 -> A playing
}
function removeTransition(e) {
if (e.propertyName !== 'transform') return;
// console.log(e.target);
e.target.classList.remove('playing');
}
window.addEventListener('keydown', playSound);
const keys = document.querySelectorAll('.key');
// 不需要i 语义化
for (let key of keys) {
key.addEventListener('transitionend', removeTransition);
}
分析:
- 键盘按下监听:通过
window.addEventListener('keydown', playSound);实现监听用户按下键盘的事件,当用户按下一个键盘键时调用playSound(e)函数:
- 获取按键代码,使用
e.keyCode获取用户按下的键的键盘码keyCode,也就是找到与用户按下键盘按键相对应的div容器; - 使用
document.querySelector()方法,根据键盘码在页面中查找对应的数据属性 (data-key) 的.key元素,也就是找到与用户按键相对应的<audio>标签,以便播放特定的声音文件; - 同样方法查找与该键关联的
<audio>元素; - 如果找到了对应的
.key元素,为该按键元素添加'playing'类,实现一些动画效果; - 调用音频元素的
play()方法播放声音。
- 过渡结束监听: 对于每个
.key元素,通过使用循环来实现transitionend事件监听器,当元素的过渡效果结束时,调用removeTransition函数:
- 检查属性名,如果事件
e的propertyName不是'transform',也就是不是我们关心的过渡效果完成,则直接返回,不做任何操作; - 如果是关心的过渡效果完成,则从事件目标,也就是按键元素中移除
'playing'类,恢复其原始的状态。
结语
快来演奏一首你的打击乐吧~