一个简单小demo:键盘打击乐

前言

好久没有写好玩的小demo了,今天来实现一个敲击键盘的打击乐小demo,具体效果如下。

代码实现原理其实很简单,给每个键盘绑定一个audio,当用户敲击键盘时,我们能够拿到一个keyCode,通过给键盘设置data-key,再写一个简单函数实现音乐播放。

下面我们直接上代码,并讲解其中一些主要的注意点。

HTML代码

Html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>HTML5商业化开发细节</title>
  <link rel="stylesheet" href="./common.css">
  <script src="./index.js"></script>
</head>

<body>
  <div class="keys">
    <div class="keys1">
      <div class="key" data-key="81">
        <div>Q</div>
        <span class="sound">clap</span>
      </div>
      <div class="key" data-key="87">
        <div>W</div>
        <span class="sound">hihat</span>
      </div>
      <div class="key" data-key="69">
        <div>E</div>
        <span class="sound">kick</span>
      </div>
      <div class="key" data-key="82">
        <div>R</div>
        <span class="sound">openhat</span>
      </div>
      <div class="key" data-key="84">
        <div>T</div>
        <span class="sound">openhat</span>
      </div>
      <div class="key" data-key="89">
        <div>Y</div>
        <span class="sound">ride</span>
      </div>
      <div class="key" data-key="85">
        <div>U</div>
        <span class="sound">snare</span>
      </div>
      <div class="key" data-key="73">
        <div>I</div>
        <span class="sound">tom</span>
      </div>
      <div class="key" data-key="79">
        <div>O</div>
        <span class="sound">tink</span>
      </div>
      <div class="key" data-key="80">
        <div>P</div>
        <span class="sound">tink</span>
      </div>
    </div>
    <div class="keys2">
      <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">openhat</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>
    <div class="keys3">
      <div class="key" data-key="90">
        <div>Z</div>
        <span class="sound">clap</span>
      </div>
      <div class="key" data-key="88">
        <div>X</div>
        <span class="sound">hihat</span>
      </div>
      <div class="key" data-key="67">
        <div>C</div>
        <span class="sound">kick</span>
      </div>
      <div class="key" data-key="86">
        <div>V</div>
        <span class="sound">openhat</span>
      </div>
      <div class="key" data-key="66">
        <div>B</div>
        <span class="sound">openhat</span>
      </div>
      <div class="key" data-key="78">
        <div>N</div>
        <span class="sound">ride</span>
      </div>
      <div class="key" data-key="77">
        <div>M</div>
        <span class="sound">snare</span>
      </div>
    </div>
  </div>

  <!-- 音频资源 -->
  <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>

  <audio src="./sounds/1.wav" data-key="81"></audio>
  <audio src="./sounds/2.wav" data-key="87"></audio>
  <audio src="./sounds/3.wav" data-key="69"></audio>
  <audio src="./sounds/4.wav" data-key="82"></audio>
  <audio src="./sounds/5.wav" data-key="84"></audio>
  <audio src="./sounds/6.wav" data-key="89"></audio>
  <audio src="./sounds/7.wav" data-key="85"></audio>
  <audio src="./sounds/8.wav" data-key="73"></audio>
  <audio src="./sounds/9.mp3" data-key="79"></audio>
  <audio src="./sounds/10.mp3" data-key="80"></audio>

  <audio src="./sounds/clap.wav" data-key="90"></audio>
  <audio src="./sounds/hihat.wav" data-key="88"></audio>
  <audio src="./sounds/kick.wav" data-key="67"></audio>
  <audio src="./sounds/openhat.wav" data-key="86"></audio>
  <audio src="./sounds/boom.wav" data-key="66"></audio>
  <audio src="./sounds/ride.wav" data-key="78"></audio>
  <audio src="./sounds/snare.wav" data-key="77"></audio>
</body>

</html>

排版没什么好讲的,这里主要是介绍一下HTML5中自定义数据属性data-key。

data-key

  • data-key 是HTML5中的自定义数据(data-*)属性之一,用于在HTML标签上存储自定义数据。在 HTML 中,你可以通过在标签上添加 data- 前缀来定义自定义数据属性。在上述应用中,我们使用每个按键的 data-key 属性存储了对应的键码(keyCode)。你可以使用任意合法的属性名来代替*部分。例如,data-colordata-user-id 等。这个属性是我们实现键盘交互非常重要的元素。

CSS部分

css 复制代码
/* 业务样式 */
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,
acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,
strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,
table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,
header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,
video {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 100%;
    font: inherit;
    vertical-align: baseline;
}

/* HTML5 display-role reset for older browsers */
article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,
section {
    display: block;
}

body {
    line-height: 1;
}

ol,ul {
    list-style: none;
}

blockquote,q {
    quotes: none;
}

blockquote:before,
blockquote:after,
q:before,
q:after {
    content: '';
    content: none;
}

table {
    border-collapse: collapse;
    border-spacing: 0;
}

html {
    height: 100vh;
    font-size: 10px;
    background: url('./2.jpg') bottom center;
    background-size: cover;
}

body,html {
    font-family: sans-serif;
}

.keys {
    /* 水平垂直居中 */
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    min-height: 100vh;
}

.keys1,
.keys2,
.keys3 {
    display: flex;
}

.key {
    border: .4rem solid #000;
    border-radius: .5rem;
    margin: 1rem;
    font-size: 1.5rem;
    padding: 1rem .5rem;
    transition: all .07s ease;
    width: 10rem;
    text-align: center;
    color: white;
    text-shadow: 0 0 .5rem black;
}

.key:hover {
    border-color: red;
}

.playing {
    transform: scale(1.1);
    border-color: #ffc600;
    box-shadow: 0 0 1rem #ffc600;
}

.key div {
    font-size: 4rem;
}

.sound {
    font-size: 1.2rem;
    text-transform: uppercase;
    letter-spacing: normal;
    color: #ffc600;
}

对于还没去过企业上班或者实习的掘友(比如博主本人^-^)来说,可能不明白为什么最开始为什么要把基本上所有标签全列出来,在大学的学习中,或者自己自学在网上上网课,大部分老师通常都是像下面这样设置。

css 复制代码
*{
  padding: 0;
  margin: 0;
}

的确很省事,对吧,不过一般企业开发却都不会使用上面这种简单的,它带来的性能是不好的。我去查询了几家大厂的网页源码,无一例外,他们都是按第一种来设置的。

豆瓣

腾讯

不过平时书写代码不太关心性能问题,我们按第二种设置也省事,不过第二种的设置我们还是需要了解的。第一种的代码可以在网上搜到,网址,reset.css,不用自己书写。

JS部分

js 复制代码
function playSound(e) {
  const keyCode = e.keyCode;
  // 标签的数据属性
  const key = document.querySelector(`
    .key[data-key="${keyCode}"]
  `)
  key && key.classList.add('playing');

  const keys = document.querySelectorAll('.key');
  // console.log(keys)
  keys.forEach((key) => {
    key.addEventListener('transitionend', function (e) {
      if (e.propertyName != 'transform') return;
      this.classList.remove('playing');
    })
  })

  const audio = document.querySelector(`
    audio[data-key="${keyCode}"]
  `)

  audio.currentTime = 0;
  audio.play();

}
window.addEventListener('keydown', playSound)

解释:

    • playSound 函数接受一个事件对象 e,代表键盘按下事件。
    • 通过 e.keyCode 获取按下的键码。
    • 使用 document.querySelector 选择器找到拥有对应键码的 .key 元素,并添加 'playing' 类,触发样式效果。
    • 通过 document.querySelectorAll 获取所有 .key 元素,为每个元素添加 transitionend 事件监听器,确保在过渡结束时移除 'playing' 类。playing类为我们之前写的样式,点击某个按钮后会呈现一种放大的样式。
    • 通过 document.querySelector 找到对应键码的音频元素,将音频的播放时间重置为 0,并播放音频。
  1. window.addEventListener('keydown', playSound):

    • playSound 函数绑定到全局 window 对象的 keydown 事件上,即当用户按下键盘上的任意键时,触发 playSound 函数。
  2. 解释细节:

  • 添加 'playing' 类使得按下的键在页面上有一个瞬时的样式效果。
  • 通过监听 transitionend 事件,确保样式效果在过渡结束后被移除,避免样式效果持续存在。
  • 通过选择器找到对应的音频元素,将播放时间重置为 0,以确保每次按下键时都从音频的起始位置开始播放。

解释一下下面这段代码,可能有些人不太了解

js 复制代码
keys.forEach((key) => {
    key.addEventListener('transitionend', function (e) {
      if (e.propertyName != 'transform') return;
      this.classList.remove('playing');
    })
})

key.addEventListener('transitionend', ...) 添加了一个事件监听器,用来监听过渡结束事件。e.propertyName 是用来检查触发过渡结束的 CSS 属性的名称。通过if (e.propertyName != 'transform') return; 判断只有当触发事件的属性是 'transform' 时才执行后续的代码。这是因为键盘按键的样式变化主要涉及到 CSS 的 transform 属性。

留言

感兴趣的掘友们可以去试试哦。本人GitHub链接,里面有音频可以下载哦♥(ˆ◡ˆԅ)。

相关推荐
WeiXiao_Hyy35 分钟前
成为 Top 1% 的工程师
java·开发语言·javascript·经验分享·后端
吃杠碰小鸡1 小时前
高中数学-数列-导数证明
前端·数学·算法
kingwebo'sZone1 小时前
C#使用Aspose.Words把 word转成图片
前端·c#·word
xjt_09011 小时前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
我是伪码农1 小时前
Vue 2.3
前端·javascript·vue.js
夜郎king2 小时前
HTML5 SVG 实现日出日落动画与实时天气可视化
前端·html5·svg 日出日落
辰风沐阳2 小时前
JavaScript 的宏任务和微任务
javascript
夏幻灵3 小时前
HTML5里最常用的十大标签
前端·html·html5
冰暮流星3 小时前
javascript之二重循环练习
开发语言·javascript·数据库
Mr Xu_3 小时前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js