音乐键盘
呈现效果:当敲击键盘中的字母按键时会发出不同的声音,并且还有动画效果。
这个案例分为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部分:
- 清除页面里所有的默认内外边距。
- 为
html
元素设置了字体大小样式,这样是为了在后续使用rem
单位提供一个基准;设置了一个背景图片,并且要求图片在垂直方向上头部对齐,水平方向居中对齐,图片不重复平铺;为了让图片不失真可以通过设置background-size
样式,再根据容器和图片的优先程度选择相应的属性。 - 将
.keys
类选择器元素设置为Flex 布局,将三行字母按键进行垂直方向排列,并且在垂直和水平方向上面进行居中对齐。 - 给
.key1
、.key2
和key3
类选择器也设置为Flex 布局,这样可以使按键元素保持水平方向排列。 - 对
.keys
容器内每个类名为.key
的子元素进行样式定义。 - 设置
.playing
类的特定样式,通过JavaScript的监听器动态增加和删除该类名达到用户按下对应按键后得到视觉反馈的动画。
小tips
-
在
background-size
样式中:cover
属性可以确保背景图片在填充元素区域时,会等比例缩放图片以完全覆盖整个区域。这样是以容器为优先选择的。
contain
属性会保持图像的宽高比,将图像缩放至能够完全包含在背景区域内。也就是说图像可能会在背景区域内留下空白,但其内容会完整显示。这样是以图片为优先选择的。
-
CSS中的常见单位:
- 绝对单位:
- px:在屏幕上显示时,一个像素通常对应屏幕上的一个物理像素点,是最常用的固定尺寸单位。
- 相对单位:
- % :通常是相对于父元素的某个尺寸的比例。比如,如果父元素宽度为 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)
}
代码逻辑:
- 通过在窗口上添加一个键盘按下的事件监听器监听用户的按键操作。
- 当用户按键盘后调用
playSound
函数。e.keyCode
表示触发事件时按下的键对应的键码。通过键码获取对应的key
元素和audio
元素,如果按错了按键就获取不了key
元素,就直接结束,如果没有按错按键就为其对应的key
元素添加playing
类实现动画效果,并且通过获取到的audio
元素播放对应的音效。
- 获取页面上所有拥有 class 名称为
key
的元素,并且对其进行for of
循环遍历操作,为每个元素添加了一个事件监听器监听transitionend
事件。 - 当触发了
key
元素的监听器后调用removeTransition
函数移除对应的key
元素中的playing
类。
你可以自己动手将喜欢的音频绑定到相应的键盘按键上制作一个属于你自己的专属音乐键盘。