HTML交响曲:打造在线打击乐社区
前言
使用html5来实现一个音乐键盘,用来实现在线打击乐。
实现效果如下
HTML
- 创建一个包含九个
.key
类的div元素的容器,每个.key
元素都有一个data-key
属性,对应键盘上的一个按键,span标签存储了与该按键相关联的声音的名称。 - audio包含了预加载的音频文件路径,每个文件都有一个src属性指向本地的音频文件路径,并且有与之对应的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("./background.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;
text-transform: uppercase;
letter-spacing: 0.1rem;
color: #ffc600;
}
.keys .key.playing {
transform: scale(1.1);
border-color: #ffc600;
box-shadow: 0 0 1rem #ffc600;
}
JS
用于实现两个主要功能:一是响应键盘按键事件来播放相应的音频,二是处理css过渡效果结束后的清理工作。
- 首先定义一个
playSound
函数,它接收一个事件参数e,作为键盘的按键事件,先获取按键的keyCode
,然后使用document.querySelector
查找与该keyCode匹配的.key
和audio
元素。找到了就添加一个playing
类。 window.addEventListener('keydown', playSound)
用于将playSound函数绑定到window的keydown事件上,当按下键盘的按键时,该函数就能被调用。- 定义一个
removeTransition
函数,用于移除元素上的playing类,它接受一个参数e事件对象,包含了事件的信息。 if (e.propertyName !== 'transform') return;
条件判断检查事件参数e的propertyName
属性是否等于字符串transform
。propertyName
属性比较特殊,它告诉开发者那个CSS属性触发了过渡效果,如果过渡效果不是由transform属性触发的,函数会立即返回,不做任何其他操作。e.target.classList.remove('playing')
表示如果过渡属性是由transform
属性触发,就会移除playing的类。以便元素回到默认状态。- for...of循环遍历keys中的每一个元素,为每个元素添加
transitionend
事件监听器。当任何一个元素的过渡效果结束时,都会调用removeTransition
函数,用于移除playing类。
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
}
window.addEventListener('keydown', playSound)
const keys = document.querySelectorAll('.key')
function removeTransition(e) {
if (e.propertyName !== 'transform') return;
// console.log(e.target, '/////');
e.target.classList.remove('playing')
}
// 不需要i 语义化
// es6 可读性高
for (let key of keys) {
key.addEventListener('transitionend', removeTransition)
}
结语
快去自己手动实现个打击乐吧
转载自:https://juejin.cn/post/7391746098681446438