게으른개발너D
[JS] JavaScript Drum Kit 본문
키보드로 두드렸을 때 화면에 나타낼 자판 모양 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
위 사이트에서 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
출처
'프로젝트 > 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 |