๐Ÿ“–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 ํ”„๋กœ์ ํŠธ ๊ฒฐ๊ณผ๋ฌผ