HTML5节奏盛宴:打造互动在线打击乐器体验

774 阅读2分钟

前言

html5让我们拥有强大的模仿能力,下面让我们通过html5来写一个音乐键盘,实现在线打击乐。

image.png

正文

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);
}

分析:

  1. 键盘按下监听:通过window.addEventListener('keydown', playSound);实现监听用户按下键盘的事件,当用户按下一个键盘键时调用playSound(e) 函数:
  • 获取按键代码,使用 e.keyCode 获取用户按下的键的键盘码keyCode,也就是找到与用户按下键盘按键相对应的div容器;
  • 使用 document.querySelector() 方法,根据键盘码在页面中查找对应的数据属性 (data-key) 的 .key 元素,也就是找到与用户按键相对应的 <audio> 标签,以便播放特定的声音文件;
  • 同样方法查找与该键关联的 <audio> 元素;
  • 如果找到了对应的 .key 元素,为该按键元素添加 'playing' 类,实现一些动画效果;
  • 调用音频元素的 play() 方法播放声音。
  1. 过渡结束监听: 对于每个 .key 元素,通过使用循环来实现 transitionend 事件监听器,当元素的过渡效果结束时,调用 removeTransition 函数:
  • 检查属性名,如果事件 e 的 propertyName 不是 'transform',也就是不是我们关心的过渡效果完成,则直接返回,不做任何操作;
  • 如果是关心的过渡效果完成,则从事件目标,也就是按键元素中移除 'playing' 类,恢复其原始的状态。

结语

快来演奏一首你的打击乐吧~

image.png