音乐键盘:独属于程序员的浪漫

音乐键盘

呈现效果:当敲击键盘中的字母按键时会发出不同的声音,并且还有动画效果。

这个案例分为HTML部分、CSS部分和JavaScript部分。在CSS部分中使用Stylus编译器将.styl文件编译为标准的.css文件,然后将生成的.css文件链接到HTML文档中,以便浏览器可以加载并应用样式。

HTML部分

html 复制代码
<div class="keys">
    <div class="key1">
        <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="key2">
        <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="key3">
        <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="81"></audio>
<audio src="./sounds/hihat.wav" data-key="87"></audio>
<audio src="./sounds/kick.wav" data-key="69"></audio>
<audio src="./sounds/openhat.wav" data-key="82"></audio>
<audio src="./sounds/clap.wav" data-key="84"></audio>
<audio src="./sounds/ride.wav" data-key="89"></audio>
<audio src="./sounds/snare.wav" data-key="85"></audio>
<audio src="./sounds/tom.wav" data-key="73"></audio>
<audio src="./sounds/tink.wav" data-key="79"></audio>
<audio src="./sounds/tink.wav" data-key="80"></audio>

<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/clap.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/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/clap.wav" data-key="66"></audio>
<audio src="./sounds/ride.wav" data-key="78"></audio>
<audio src="./sounds/snare.wav" data-key="77"></audio>

用一个类名为keys的大盒子包裹3个子盒子,分别对应键盘的三行字母按键。

其中每一个子盒子里的元素都有一个key类和一个特定的 data-key 属性用于标识对应的键盘按键,并且内部都一个显示字母的div标签和描述声音的span标签。

还有一系列的 audio 标签,每一个音频都是通过 data-key 属性和按键进行对应。也可以根据自己的喜好设置不一样的音频。

你会好奇data-key的值是怎么来的吗?在JavaScript部分会揭秘。

CSS部分

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

html {
  font-size: 10px;
  background: url("./background1.jpg") top center no-repeat;
  background-size: cover;
}

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

body {
  height: 100vh;
}

.keys {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  min-height: 100vh;
}

.key1,
.key2,
.key3 {
  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: #c8e6ff;
  background: rgba(0, 0, 0, 0.4);
  text-shadow: 0 0 0.5rem #000;
  transition: all 0.7s ease;
}

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

.keys .key .sound {
  font-size: 1.2rem;
  text-transform: uppercase;
  letter-spacing: 0.1rem;
  color: #87ceeb;
}

.keys .key.playing {
  transform: scale(1.3);
  border-color: #87ceeb;
  box-shadow: 0 0 1rem #87ceeb;
}

CSS部分通过将编写.styl文件后编译为标准的.css文件,这样可以减少代码量。

CSS部分:

  1. 清除页面里所有的默认内外边距。
  2. html元素设置了字体大小样式,这样是为了在后续使用rem单位提供一个基准;设置了一个背景图片,并且要求图片在垂直方向上头部对齐,水平方向居中对齐,图片不重复平铺;为了让图片不失真可以通过设置background-size样式,再根据容器和图片的优先程度选择相应的属性。
  3. .keys类选择器元素设置为Flex 布局,将三行字母按键进行垂直方向排列,并且在垂直和水平方向上面进行居中对齐。
  4. .key1.key2key3类选择器也设置为Flex 布局,这样可以使按键元素保持水平方向排列。
  5. .keys容器内每个类名为.key的子元素进行样式定义。
  6. 设置.playing类的特定样式,通过JavaScript的监听器动态增加和删除该类名达到用户按下对应按键后得到视觉反馈的动画。

小tips

  1. background-size样式中:

    1. cover属性可以确保背景图片在填充元素区域时,会等比例缩放图片以完全覆盖整个区域。这样是以容器为优先选择的。
  1. contain属性会保持图像的宽高比,将图像缩放至能够完全包含在背景区域内。也就是说图像可能会在背景区域内留下空白,但其内容会完整显示。这样是以图片为优先选择的。
  1. CSS中的常见单位:

    1. 绝对单位:
      • px:在屏幕上显示时,一个像素通常对应屏幕上的一个物理像素点,是最常用的固定尺寸单位。
    2. 相对单位:
      • % :通常是相对于父元素的某个尺寸的比例。比如,如果父元素宽度为 100px,子元素宽度设置为 50%,则子元素宽度为 50px。
      • em:相对于当前元素的字体大小。如果未设置,则继承自父元素。它的值取决于当前元素的字体大小。如果当前元素字体大小为 16px,那么 1em 就等于 16px。
      • rem:相对于根元素(通常是<html>元素)的字体大小,提供了一致的尺寸缩放基础。
      • vw/vh:分别表示可视窗口的宽度和可视窗口的高度的1%。例如,1vw等于可视窗口宽度的1%。

JavaScript部分

javascript 复制代码
function playSound(e) {
    let keyCode = e.keyCode;
    const key = document.querySelector(`.key[data-key="${keyCode}"]`);
    const audio = document.querySelector(`audio[data-key="${keyCode}"]`);
    if (!key) return;
    key.classList.add('playing');
    audio.play();
}
window.addEventListener('keydown', playSound)
const keys = document.querySelectorAll('.key');
function removeTransition(e) {
    if (e.propertyName !== 'transform') return;
    e.target.classList.remove('playing');
}
for (let key of keys) {
    key.addEventListener('transitionend', removeTransition)
}

代码逻辑:

  1. 通过在窗口上添加一个键盘按下的事件监听器监听用户的按键操作。
  2. 当用户按键盘后调用playSound函数。
    • e.keyCode表示触发事件时按下的键对应的键码。通过键码获取对应的key元素和audio元素,如果按错了按键就获取不了key元素,就直接结束,如果没有按错按键就为其对应的key元素添加playing类实现动画效果,并且通过获取到的audio元素播放对应的音效。
  3. 获取页面上所有拥有 class 名称为 key 的元素,并且对其进行for of循环遍历操作,为每个元素添加了一个事件监听器监听 transitionend 事件。
  4. 当触发了key 元素的监听器后调用removeTransition函数移除对应的key元素中的playing类。

你可以自己动手将喜欢的音频绑定到相应的键盘按键上制作一个属于你自己的专属音乐键盘。

相关推荐
魏大帅。1 分钟前
Axios 的 responseType 属性详解及 Blob 与 ArrayBuffer 解析
前端·javascript·ajax
花花鱼7 分钟前
vue3 基于element-plus进行的一个可拖动改变导航与内容区域大小的简单方法
前端·javascript·elementui
k093311 分钟前
sourceTree回滚版本到某次提交
开发语言·前端·javascript
EricWang135832 分钟前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
September_ning32 分钟前
React.lazy() 懒加载
前端·react.js·前端框架
web行路人42 分钟前
React中类组件和函数组件的理解和区别
前端·javascript·react.js·前端框架
番茄小酱00143 分钟前
Expo|ReactNative 中实现扫描二维码功能
javascript·react native·react.js
子非鱼9211 小时前
【Ajax】跨域
javascript·ajax·cors·jsonp
超雄代码狂1 小时前
ajax关于axios库的运用小案例
前端·javascript·ajax
长弓三石1 小时前
鸿蒙网络编程系列44-仓颉版HttpRequest上传文件示例
前端·网络·华为·harmonyos·鸿蒙