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

音乐键盘

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

这个案例分为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类。

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

相关推荐
加班是不可能的,除非双倍日工资14 分钟前
css预编译器实现星空背景图
前端·css·vue3
wyiyiyi1 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip1 小时前
vite和webpack打包结构控制
前端·javascript
excel2 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端
阿华的代码王国2 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
一条上岸小咸鱼2 小时前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin
Jimmy2 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
ZXT2 小时前
promise & async await总结
前端
Jerry说前后端2 小时前
RecyclerView 性能优化:从原理到实践的深度优化方案
android·前端·性能优化
画个太阳作晴天2 小时前
A12预装app
linux·服务器·前端