JS30 - 01 JavaScript Drum Kit
01 JavaScript Drum Kit
效果展示
通过按键来播放音频及改样式。
相关知识
<kbd>标签:定义键盘文本,表示文本是从键盘上键入的。将产生一个行内元素,以浏览器的默认 monospace 字体显示。
data-* 属性:
querySelector() 方法:
- 接收一个CSS选择符,返回与该模式匹配的第一个元素,如果没有找到匹配的元素,返回null
- querySelector() 获取静态集合,获取到元素之后就和 html 中的这个元素没有关系了。即只要不再取一次,则维持原来内容、不变
- getElementBy*() 获取动态集合,每一次在 Javascript 函数中使用这个变量的时候都会再去访问一下这个变量对应的 html 元素
立即函式
(function() {})();
:classList 属性:
返回元素的类名,作为 DOMTokenList 对象
为
<div>
元素添加 class:document.getElementById("myDIV").classList.add("mystyle");
currentTime 属性:
- 设置或返回视频播放的当前位置;当设置该属性时,播放会跳跃到指定的位置
- 设置为 0 可以让例子里的音频连续播放
addEventListener() 方法:
- document.addEventListener(event, function, useCapture)
- 当 event 为 transitionend 时,表示该事件在 CSS 完成过渡后触发
forEach() 方法:
- 用于调用数组的每个元素,并将元素传递给回调函数
currentTarget 事件属性:返回其监听器触发事件的节点,即当前处理该事件的元素、文档或窗口。
代码展示
思路
style.css
html {
font-size: 10px;
background: url(img/stars.jpg);
background-size: cover;
}
body, html {
margin: 0;
padding: 0;
font-family: sans-serif;
}
.keys {
display: flex;
flex: 1;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.key {
margin: 1rem;
padding: 1rem .5rem;
width: 10rem;
color: white;
text-align: center;
text-shadow: 0 0 .5rem black;
font-size: 1.5rem;
background: rgba(0,0,0,0.4);
border: .4rem solid black;
border-radius: .5rem;
transition: all .07s ease;
}
.playing {
border-color: #ffc600;
box-shadow: 0 0 1rem #ffc600;
transform: scale(1.1);
}
kbd {
display: block;
font-size: 4rem;
}
.sound {
font-size: 1.2rem;
color: #ffc600;
text-transform: uppercase;
letter-spacing: .1rem;
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="keys">
<div data-key="65" class="key">
<kbd>A</kbd>
<span class="sound">clap</span>
</div>
<div data-key="83" class="key">
<kbd>S</kbd>
<span class="sound">hihat</span>
</div>
<div data-key="68" class="key">
<kbd>D</kbd>
<span class="sound">kick</span>
</div>
<div data-key="70" class="key">
<kbd>F</kbd>
<span class="sound">openhat</span>
</div>
<div data-key="71" class="key">
<kbd>G</kbd>
<span class="sound">boom</span>
</div>
<div data-key="72" class="key">
<kbd>H</kbd>
<span class="sound">ride</span>
</div>
<div data-key="74" class="key">
<kbd>J</kbd>
<span class="sound">snare</span>
</div>
<div data-key="75" class="key">
<kbd>K</kbd>
<span class="sound">tom</span>
</div>
<div data-key="76" class="key">
<kbd>L</kbd>
<span class="sound">tink</span>
</div>
</div>
<audio data-key="65" src="sounds/clap.wav"></audio>
<audio data-key="83" src="sounds/hihat.wav"></audio>
<audio data-key="68" src="sounds/kick.wav"></audio>
<audio data-key="70" src="sounds/openhat.wav"></audio>
<audio data-key="71" src="sounds/boom.wav"></audio>
<audio data-key="72" src="sounds/ride.wav"></audio>
<audio data-key="74" src="sounds/snare.wav"></audio>
<audio data-key="75" src="sounds/tom.wav"></audio>
<audio data-key="76" src="sounds/tink.wav"></audio>
<script>
(function () {
function playSound(e) {
// data-key 后的 keyCode 别忘记加引号
const audio = document.querySelector('audio[data-key="' + e.keyCode + '"]');
// ES6 写法
const key = document.querySelector(`div[data-key="${e.keyCode}"]`);
if (audio) {
audio.currentTime = 0;
audio.play();
}
if (key)
key.classList.add("playing");
}
function removeTransition(e) {
// 查看 propertyName
// console.log(e);
// 在这个页面中,发生 transition 的样式属性有多个(box-shadow, transform, border-color),所以需要添加一个判断语句,使每发生一次按键事件时,只去除一次样式。下方代码中 transform 也可改为 border-left-color 等。
if (e.propertyName === 'transform') {
e.currentTarget.classList.remove('playing');
}
}
window.addEventListener('keydown',
// function (e) {
// console.log(e.keyCode);
// }
playSound);
document.querySelectorAll('.key').forEach(function (key) {
key.addEventListener('transitionend', removeTransition);
});
})();
</script>
</body>
</html>
参考
赞 (0)