Javascript_30_01_02

Derek·2020년 12월 14일
0

javascript_30

목록 보기
2/31
post-thumbnail

안녕하세요!

Derek입니다. 🙂

오늘은 첫 게시물의 sequel을 다루려고 합니다! ✨


01. Javascript Drum Kit

이전 게시물 및 Javascript Drum Kit 가 뭔지 모르신다면..!

https://velog.io/@ghdtjrrl94/Javascript30

이곳을 눌러서 확인 부탁드리겠습니다. 😛


이전 게시물에 Derek 구현 코드를 확인해보시면, 저는 switch-case 문으로 모든 keyCode 조건을 분기했었는데요,

function handleKeyDown(event){
    switch(event.keyCode){
        case 65:
            currentKeyCode = "65";
            playSound();
            break;
        case 83:
            currentKeyCode = "83";
            playSound();
            break;
        ...
        
        

이런식으로 9개의 keyCode 를 토대로 일일히 case 를 만들었었습니다.
또한, 그렇게 분기되어서 각각은 currentKeyCode 값을 가지고 다음 playSound() 함수를 수행합니다.

function playSound(){
    // add "playing" class
    let targetKey = document.querySelector(`div[data-key = "${currentKeyCode}"]`);
    targetKey.classList.add("playing");

    // audio play
    let audioKey = document.querySelector(`audio[data-key = "${currentKeyCode}"]`);
    audioKey.play();

    // remove playing class 
    setTimeout(() => targetKey.classList.remove("playing"), 500);
    //targetKey.classList.remove("playing");
}

또한 playing class를 지워주는 (잠깐 노란색으로 변하는 과정) 작업은 setTimeout 함수로 비동기적으로 0.5초 후에 실행하도록 설계했습니다.

이 모든 함수들은 사실

window.addEventListener("keydown", handleKeyDown);

eventListener 로 부터 시작이 되구요.




Wes Bos 구현 코드

Wes Bos는 https://javascript30.com/ 를 이끌고 강의를 하는 분인데요,
이분의 강의 코드를 정리하고자 합니다.

아주.. 🐶고수이신것 같더라구요! 배울점이 많아서 기록하려고 합니다 😂

  function removeTransition(e) {
    if (e.propertyName !== 'transform') return;
    e.target.classList.remove('playing');
  }

  function playSound(e) {
    const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
    const key = document.querySelector(`div[data-key="${e.keyCode}"]`);
    if (!audio) return;

    key.classList.add('playing');
    audio.currentTime = 0;
    audio.play();
  }

  const keys = Array.from(document.querySelectorAll('.key'));
  keys.forEach(key => key.addEventListener('transitionend', removeTransition));
  window.addEventListener('keydown', playSound);

코드의 흐름대로 내용을 제가 새로 접한 내용을 바탕으로 정리해보겠습니다!


1. Adding playing class

function playSound(e) {
    const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
    const key = document.querySelector(`div[data-key="${e.keyCode}"]`);
    if (!audio) return;

    key.classList.add('playing');
    audio.currentTime = 0;
    audio.play();
  }

window.addEventListener('keydown', playSound);

조금은 제 코드와 비슷하지만, switch-case 를 쓰지 않고 바로 event.keyCode 로 접근하였습니다.

const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
const key = document.querySelector(`div[data-key="${e.keyCode}"]`);

백틱을 사용해서 event 로 넘어온 인자를 바로 keyCode 로 사용하면 굳이 제 코드처럼 switch-case 를 쓰지 않아도 되더라구요. 😅

중간에 audio.play() 전에 있는 audio.currenTime = 0; 를 잠깐 언급드리겠습니다!
저 구문이 없다면, 키보드 a, s, d, f, g, h, j, k, l 중 하나를 연속해서 빠르게 연타할때 약간 느리게 소리가 들리더라구요.

이는 sound.wav 파일의 재생 시간 때문에 빠르게 재생이 처음부터 안되고, 약간의 delay가 있는 것 처럼 재생되는 것이였습니다.

이를 해결하기 위해 매번 그 오디오 파일 (sound.wav) 을 처음으로 rewind 해주는 구문이라고 보시면 될 것 같아요!

2. Deleting playing class

저는 추가된 playing class를 지울때, 비동기적으로 setTimeout 함수를 통해 0.5초 후에 지우도록 했었습니다. 하지만 wes Bos 님의 코드를 보니 더 고급진 방법이 있더라구요..!

  function removeTransition(e) {
    if (e.propertyName !== 'transform') return;
    e.target.classList.remove('playing');
  }
  
  const keys = Array.from(document.querySelectorAll('.key'));
  keys.forEach(key => key.addEventListener('transitionend', removeTransition));

먼저 querySelectorAll 를 통해 class 값이 key 인 모든 class들을 찾아 list 형태로 keys에 저장합니다.

그렇게 생성한 element 들에 대해서 하나하나 addEventListener 를 설정해주기보다는,

keys.forEach(key => key.addEventListener('transitionend', removeTransition));

이렇게 forEach 구문을 통해 하나하나에 대한 eventListener 를 설정해주었습니다.
저는 개인적으로 이 부분이 가장 효율적이다고 생각이 들어요!

사실 애초에 list 형태인 keys 에는 이런 코드는 에러를 발생시키는데요,

 const keys = Array.from(document.querySelectorAll('.key'));
 keys.addEventListener("click", handleClick);

2번째 문장인 keys.addEventListener("click", handleClick);list 형태인 keys 에 이벤트를 등록했기 때문에, 오류를 발생시킵니다.

이를 forEach 를 통해 간편하게 event 를 등록하는 게 정말 현명하다고 느껴졌습니다! 😆


또한, transitionend 라는 다소 생소한 이벤트를 사용했는데요,
그 정의는 이렇다고 합니다!

CSS를 전환이 완료되면 transitionend 이벤트가 발생한다.

즉 이번 Drum kit 프로젝트에서는 playing class 가 추가되어 생기는 transition 이 끝나면,

removeTransition 함수를 실행시키는 형식입니다! removeTransition 함수는,

  function removeTransition(e) {
    if (e.propertyName !== 'transform') return;
    e.target.classList.remove('playing');
  }

이렇게 정의가 되어있는데요, 간단합니다! 먼저 발생한 이벤트에 transform 이 없다면 아무런 행동을 취하지 않고, 있다면 playing class를 remove 하는 로직입니다.





이렇게 wes Bos 의 참고 코드도 리뷰해보았는데요, 간단한 구문이라도 매우 효율적으로 쓸 수 있음에 감탄하며.. 언제쯤 저렇게 되려나 고민도 하게 되는 강의였습니다..! 😥


틀린내용이나 수정할 내용이 있다면 언제든지 피드백 부탁드립니다!

감사합니다!🤗

profile
Whereof one cannot speak, thereof one must be silent.

0개의 댓글