html 및 css는 강의에서 제공
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>JS Drum Kit</title>
<link rel="stylesheet" href="style.css" />
<link rel="icon" href="https://fav.farm/🔥" />
</head>
<body>
<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>
</body>
</html>
html {
font-size: 10px;
background: url("./background.jpg") bottom center;
background-size: cover;
}
body,
html {
margin: 0;
padding: 0;
font-family: sans-serif;
}
.keys {
display: flex;
flex: 1;
min-height: 100vh;
align-items: center;
justify-content: center;
}
.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;
}
.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;
}
function playSound(e) {
const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
const key = document.querySelector(`.key[data-key="${e.keyCode}"]`);
if (!audio) return; // keyCode와 일치하는 엘리먼트 없으면 함수 종료
audio.currentTime = 0; // 처음으로 되감기
audio.play();
key.classList.add("playing");
}
function removeTransition(e) {
if (e.propertyName !== "transform") return; // 'transform'이 아닌 propertyName은 생략
console.log(e.propertyName);
this.classList.remove("playing");
}
const keys = document.querySelectorAll(".key");
keys.forEach((key) =>
key.addEventListener("transitionend", removeTransition)
);
window.addEventListener("keydown", playSound);
소리가 나는 프로젝트라 이 블로그에서는 해당 부분을 보여줄 수 없다는 것이 아쉽다ㅠㅠ
분명 소리가 나고 있다. 마음으로 듣기를 바란다.
데이터셋은 쉽게 말하면 html에서 변수처럼 사용할 수 있는 속성이다. date-속성명
이와 같은 형식으로 엘리먼트에 추가한다. 데이터셋은 자바스크립트의 dataset
프로퍼티 또는 getAttribute()
메서드를 통해 접근 가능하다.
위의 소스코드에서는 각각의 div
와 audio
엘리먼트에 data-key
라는 속성을 추가해 keyCode 번호를 할당했다.
데이터셋에 관해서는 아래의 블로그에서 공부하면 좋을 듯하다.
데이터셋 속성 더 알아보기
우리가 누르는 키보드의 키들은 각각 고유한 코드번호를 가지고 있다.
콘솔로 찍어보면 해당 객체는 keyCode라는 고유한 값을 가진다.
이를 통해 해당 값과 부합하는 data-key
를 가진 엘리먼트에 접근할 수 있다.
이런 이벤트가 있는지도 몰랐다. 이 이벤트는 CSS에서 적용한 transition이 경과하면 발생한다. 이 프로젝트에서는 클래스를 지우는 방법으로 transitionend 이벤트를 활용했다.
아래와 같이 특정 엘리먼트의 transition이 끝나면 어떤 스타일 요소가 transition이 적용되었는지 확인할 수 있다.