๐Ÿ“–Day 1 - JAVASCRIPT DRUM KIT

JavaScript 30์˜ Day 1 ํ”„๋กœ์ ํŠธ๋Š” '๋“œ๋Ÿผ ํ‚ท ๋งŒ๋“ค๊ธฐ'์ด๋‹ค. ํ™”๋ฉด์— ๋งค์นญ ๋œ ํ‚ค๋ณด๋“œ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์—ฐ๊ฒฐ๋œ audio ํŒŒ์ผ์„ ์žฌ์ƒํ•˜๋Š” ํ”„๋กœ์ ํŠธ์ด๋‹ค.

๐Ÿค“๐Ÿ“„์ฝ”๋“œ ๋ชจ์•„๋ณด๊ธฐ

HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>JS Guitar Kit</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="keys">
<div class="up-key">
<div data-key="q" class="key">
<kbd>Q</kbd>
<span class="sound">A2A3</span>
</div>
<div data-key="w" class="key">
<kbd>W</kbd>
<span class="sound">A3</span>
</div>
<div data-key="e" class="key">
<kbd>E</kbd>
<span class="sound">B2</span>
</div>
<div data-key="r" class="key">
<kbd>R</kbd>
<span class="sound">B3</span>
</div>
<div data-key="u" class="key">
<kbd>U</kbd>
<span class="sound">B3B4</span>
</div>
<div data-key="i" class="key">
<kbd>I</kbd>
<span class="sound">B4</span>
</div>
<div data-key="o" class="key">
<kbd>O</kbd>
<span class="sound">C#3</span>
</div>
<div data-key="p" class="key">
<kbd>P</kbd>
<span class="sound">C#3C#4</span>
</div>
</div>
<div class="down-key">
<div data-key="a" class="key">
<kbd>A</kbd>
<span class="sound">C#4</span>
</div>
<div data-key="s" class="key">
<kbd>S</kbd>
<span class="sound">D#4</span>
</div>
<div data-key="d" class="key">
<kbd>D</kbd>
<span class="sound">D3</span>
</div>
<div data-key="f" class="key">
<kbd>F</kbd>
<span class="sound">D5</span>
</div>
<div data-key="j" class="key">
<kbd>J</kbd>
<span class="sound">E2</span>
</div>
<div data-key="k" class="key">
<kbd>K</kbd>
<span class="sound">E4</span>
</div>
<div data-key="l" class="key">
<kbd>L</kbd>
<span class="sound">F2</span>
</div>
<div data-key=";" class="key">
<kbd>:</kbd>
<span class="sound">F2F3</span>
</div>
</div>
</div>
<audio data-key="q" src="./sounds/A2A3.wav"></audio>
<audio data-key="w" src="./sounds/A3.wav"></audio>
<audio data-key="e" src="./sounds/B2.wav"></audio>
<audio data-key="r" src="./sounds/B3.wav"></audio>
<audio data-key="u" src="./sounds/B3B4.wav"></audio>
<audio data-key="i" src="./sounds/B4.wav"></audio>
<audio data-key="o" src="./sounds/C_3.wav"></audio>
<audio data-key="p" src="./sounds/C_3C_4.wav"></audio>
<audio data-key="a" src="./sounds/C_4.wav"></audio>
<audio data-key="s" src="./sounds/D_4.wav"></audio>
<audio data-key="d" src="./sounds/D3.wav"></audio>
<audio data-key="f" src="./sounds/D5.wav"></audio>
<audio data-key="j" src="./sounds/E2.wav"></audio>
<audio data-key="k" src="./sounds/E4.wav"></audio>
<audio data-key="l" src="./sounds/F2.wav"></audio>
<audio data-key=";" src="./sounds/F2F3.wav"></audio>
<script src="main.js"></script>
</body>
</html>

CSS

html {
font-size: 10px;
background: url("./images/background.jpg") center;
background-size: cover;
}
body,
html {
margin: 0;
padding: 0;
font-family: sans-serif;
}
.keys {
display: flex;
flex-direction: column;
min-height: 100vh;
align-items: center;
justify-content: center;
}
.up-key,
.down-key {
display: flex;
}
.key {
border: 0.4rem solid black;
border-radius: 0.5rem;
margin: 1rem;
font-size: 1.5rem;
padding: 1rem 0.5rem;
transition: all 0.07s ease;
width: 10rem;
text-align: center;
color: white;
background: rgba(0, 0, 0, 0.4);
text-shadow: 0 0 0.5rem black;
}
.up-key .key:nth-child(4) {
margin-right: 25rem;
}
.down-key .key:nth-child(4) {
margin-right: 10rem;
}
.playing {
transform: scale(1.1);
border-color: #ffc600;
box-shadow: 0 0 1rem #ffc600;
}
kbd {
display: block;
font-size: 4rem;
}
.sound {
font-size: 1.2rem;
text-transform: uppercase;
letter-spacing: 0.1rem;
color: #ffc600;
}

JavaScript

function playSound(e) {
console.log(e.key);
const audio = document.querySelector(`audio[data-key='${e.key}']`);
const key = document.querySelector(`.key[data-key='${e.key}']`);
if (audio) {
audio.currentTime = 0; // rewind to the start (์ฒ˜์Œ์œผ๋กœ ๋˜๋Œ๋ฆฐ๋‹ค.)
audio.play();
key.classList.add("playing");
}
}
function removeTransition(e) {
if (e.propertyName === "transform") {
this.classList.remove("playing");
}
}
window.addEventListener("keydown", playSound);
const keys = document.querySelectorAll(".key");
keys.forEach((key) => key.addEventListener("transitionend", removeTransition));

๐Ÿ”Ž์ฝ”๋“œ ์„ค๋ช…

  1. ๊ฐ€์žฅ ๋จผ์ € ํ•ด๋‹น ํ‚ค๋ณด๋“œ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด audio๊ฐ€ ์žฌ์ƒ๋˜์–ด์•ผ ํ•œ๋‹ค. ๊ฐ•์˜์—์„œ๋Š” KeyboardEvent.keyCode๋ฅผ ์ด์šฉํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ๋ˆ„๋ฅธ ํ‚ค์˜ ๊ฐ’์„ ๋ฐ˜ํ™˜๋ฐ›์•˜์ง€๋งŒ, MDN ๋ฌธ์„œ๋ฅผ ํ™•์ธํ•ด๋ณด๋‹ˆ Deprecated(๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค) ๋ผ๊ณ  ๋˜์–ด์žˆ์–ด, KeyboardEvent.key๋ฅผ ์ด์šฉํ•ด ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ–ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์–ป์€ ๊ฐ’์„ audio์˜ data-key๋ผ๋Š” ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’๊ณผ ๋น„๊ตํ•˜๊ณ  ๋™์ผํ•œ ๊ฒฝ์šฐ ํ•ด๋‹น audio ํŒŒ์ผ์„ ์žฌ์ƒํ•œ๋‹ค.

  2. ์ด์ œ ํ‚ค๋ณด๋“œ๋ฅผ ๋ˆŒ๋ €์„ ๋•Œ, ์†Œ๋ฆฌ๋Š” ๋‚˜์˜ค์ง€๋งŒ ๋˜‘๊ฐ™์€ ๋ฒ„ํŠผ์„ ์—ฌ๋Ÿฌ๋ฒˆ ๋ˆ„๋ฅผ ๊ฒฝ์šฐ ์ด์ „์˜ audio ํŒŒ์ผ์ด ๋๋‚˜์ง€ ์•Š์•˜๋‹ค๋ฉด ์ƒˆ๋กœ์šด ์†Œ๋ฆฌ๊ฐ€ ๋‚˜์˜ค์ง€ ์•Š๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ, audio์˜ HTMLMediaElement.currentTime์„ 0์œผ๋กœ ์„ค์ •ํ•ด์ค€๋‹ค. audio ํŒŒ์ผ์˜ ์ฒ˜์Œ(0์ดˆ)์œผ๋กœ ๋Œ์•„๊ฐ€ ์žฌ์ƒํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

  3. ๋‹ค์Œ์œผ๋กœ๋Š”, ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ์‹œ๊ฐ์ ์ธ ํšจ๊ณผ๋ฅผ ์ค€๋‹ค. key.classList.add('playing')์„ ์ด์šฉํ•ด ํ‚ค๋ณด๋“œ์˜ ๋ฒ„ํŠผ์— ํ•ด๋‹นํ•˜๋Š” element์˜ class์— playing์„ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

  4. ๋งˆ์ง€๋ง‰์œผ๋กœ, ํšจ๊ณผ๊ฐ€ ์ ์šฉ๋œ ๋ฒ„ํŠผ์„ ์›์ƒํƒœ๋กœ ๋˜๋Œ๋ ค์•ผ ํ•œ๋‹ค. transitionend ์ด๋ฒคํŠธ๋Š” CSS์˜ transition์ด ์™„๋ฃŒ๋œ ์‹œ์ ์— ์‹คํ–‰๋˜๋Š”๋ฐ, key๋ผ๋Š” class๋ฅผ ๊ฐ€์ง„ ๋ชจ๋“  element์—์„œ playing์ด๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ์‚ญ์ œํ•˜๋„๋ก ํ•œ๋‹ค.

๐Ÿš€TIL(Today I Learned)

  • ๋ฌด์–ธ๊ฐ€๋ฅผ ๋งŒ๋“ค์–ด๋ณด๋Š”๊ฑด ์ƒ๊ฐ๋ณด๋‹ค ํ›จ์”ฌ ์–ด๋ ค์› ๋‹ค.
  • ๊ฐ•์˜๋ฅผ ๋“ค์œผ๋ฉด์„œ๋„ ์™œ ์ €๋ ‡๊ฒŒ ๋˜๋Š”์ง€ ๋ชจ๋ฅผ ๋•Œ๋Š” MDN์„ ํ™œ์šฉํ•˜๊ฑฐ๋‚˜ ๊ตฌ๊ธ€๋ง์„ ์ ๊ทน ํ™œ์šฉํ•ด์•ผํ–ˆ๋‹ค.
  • addEventListener, querySelector, classList, KeyboardEvent, HTMLMediaElement

JavaScript 30 ํ”„๋กœ์ ํŠธ ๊ฒฐ๊ณผ๋ฌผ