게으른개발너D

[JS] JavaScript Drum Kit 본문

프로젝트/Side Project

[JS] JavaScript Drum Kit

lazyhysong 2023. 3. 24. 16:36

키보드로 두드렸을 때 화면에 나타낼 자판 모양 box와

키 값에 맞는 소리를 낼 수 있도록 audio를 작성한다.

<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>

 

key box에 해당되는 소리를 가진 audio는 같은 data-key 값을 가지고 있다.

 

https://www.toptal.com/developers/keycode

 

JavaScript Key Code Event Tool | Toptal®

KeyCode.Info allows users to press any key and instantly get the JavaScript Key or Key Code KeyboardEvent. Check out the Tool and Event List.

www.toptal.com

위 사이트에서 key code를 알 수 있다.


function playSound(e) {
  const keyCode = e.keyCode;
  const audio = document.querySelector(`audio[data-key="${keyCode}"]`);
  if(!audio) return; // stop the function from running all together
  
  audio.play();
}

window.addEventListener("keydown", playSound);

keydown 이벤트를 추가하여 키보드 클릭 시 playSound 함수를 호출하게 만든다.

키보드 이벤트를 console 에서 찍어보면 이렇게 나오는데

누른 키보드의 code는 keyCode에서 찾아볼 수 있다.

따라서 keyCode에 해당하는 data-key 값을 가진 audio를 찾아내어 play를 시킨다.

 

이렇게 하면 같은 키를 연속으로 누를 때 약간의 텀이 생기게 되어

자연스럽게 드럼 연주를 할 수가 없다.

 

function playSound(e) {
  console.log(e);
  const keyCode = e.keyCode;
  const audio = document.querySelector(`audio[data-key="${keyCode}"]`);
  if(!audio) return; // stop the function from running all together
  audio.currentTime = 0; // rewind to the start
  audio.play();
}

currentTime = 0 을 추가하여 바로바로 연속으로 연주할 수 있도록 만든다.


이제 클릭한 키에 해당하는 box에 스타일 class를 넣어준 후 지우는 구현을 할 것이다.

function playSound(e) {
  console.log(e);
  const keyCode = e.keyCode;
  const audio = document.querySelector(`audio[data-key="${keyCode}"]`);
  const key = document.querySelector(`.key[data-key="${keyCode}"]`);
  if(!audio) return; // stop the function from running all together
  audio.currentTime = 0; // rewind to the start
  audio.play();
  key.classList.add("playing");
}

playSound 함수에 playing이라는 class를 넣어주는 구현을 넣는다.

 

.key {
  border: .4rem solid black;
  border-radius: .5rem;
  margin: 1rem;
  font-size: 1.5rem;
  padding: 1rem .5rem;
  transition: all .07s ease;
  width: 10rem;
  text-align: center;
  color: white;
  background: rgba(0,0,0,0.4);
  text-shadow: 0 0 .5rem black;
}

.playing {
  transform: scale(1.1);
  border-color: #ffc600;
  box-shadow: 0 0 1rem #ffc600;
}

key에는 transition: all 0.07s ease 가 들어가 있는데

playing 이 추가되면 0.07초동안 변화가 된다.

따라서 0.07초 후에 바로 class를 제거해주기 위해 setTimeout을 써도 되지만

그렇게 하면 css의 transition 값이나 setTimeout의 초 값을 변경 할 시 같이 변경해줘야하는 번거로움이 있다.

 

그래서 transitionend라는 이벤트를 이용한다.

 

function removeTransition(e) {
  // console.log(e);
  if(e.propertyName !== "transform") return; // skip it if it's not a transform.
  this.classList.remove("playing");
};

const keys = document.querySelectorAll(".key");
keys.forEach((key => key.addEventListener("transitionend", removeTransition)));

모든 key들을 불러와서 forEach로 이벤트를 추가해 준다.

그럼 각각의 key들이 playing이라는 class가 추가되어 transition의 변화가 생겼을 경우

transitionend로 인해 이 변화의 마지막에 removeTransition 함수를 실행할 수 있게 된다.

removeTransition 함수가 실행되었을 때 각각의 key들에 발생하는 event들을 

console로 확인해 보면 이렇게 나온다.

propertyName을 확인해 보면 

key에서 변화된 부분을 확인할 수 있는데

우리는 transform이 활성화된 key를 찾아서 그 key에만 playing class를 제거해 주면 된다.

 

 

 

완성된 화면이 이렇게!

 

 

 

 

 

 

https://github.com/eee0930/js_drum_kit

 

GitHub - eee0930/js_drum_kit: Web page you can play drums on a keyboard

Web page you can play drums on a keyboard. Contribute to eee0930/js_drum_kit development by creating an account on GitHub.

github.com

 

 


출처

https://javascript30.com/

 

JavaScript 30

Build 30 things with vanilla JS in 30 days with 30 tutorials

javascript30.com

 

'프로젝트 > Side Project' 카테고리의 다른 글

[TS] BlockChain 1 - Targets  (0) 2023.04.04
[JS] Analog Clock  (0) 2023.03.24
[JS] Paint App 2 - handle JS  (0) 2023.02.14
[JS] Paint App 1 - style  (0) 2023.02.14
[JS] Momentum App 6 - Style  (0) 2023.02.13
Comments