
오늘은 첫 게시물의 sequel을 다루려고 합니다! ✨
.gif)
이전 게시물 및 Javascript Drum Kit 가 뭔지 모르신다면..!
이곳을 눌러서 확인 부탁드리겠습니다. 😛
이전 게시물에 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는 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);
코드의 흐름대로 내용을 제가 새로 접한 내용을 바탕으로 정리해보겠습니다!
playing classfunction 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 해주는 구문이라고 보시면 될 것 같아요!
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 하는 로직입니다.
.gif)
이렇게 wes Bos 의 참고 코드도 리뷰해보았는데요, 간단한 구문이라도 매우 효율적으로 쓸 수 있음에 감탄하며.. 언제쯤 저렇게 되려나 고민도 하게 되는 강의였습니다..! 😥
감사합니다!🤗