https://taehyunkim3.github.io/JS30/drum.html
해당 프로젝트 링크
Bootstrap demo
taehyunkim3.github.io
왜bootstarp demo는 바꿔도 안바뀔까.
하. 겨우 찾았다.
마우스로 해당 버튼을 클릭하면, 해당 버튼에 애니메이션이 구현되도록 해야했는데,
여기서 에니메이션은 key-code로 묶여있기에, 큰 수정 없이 기능을 추가하기 위해서는
마우스 클릭을 하면 해당 요소의 data-key 값을 불러올 수 있어야 한다.
보통 해당 요소의 속성을 불러올땐 getAttribute를 사용하는데
this는 getAttribute를 사용할 수 없다. ㅠㅠ
따라서 this 대신에 addeventlistener에서 인자를 넘겨줘야하는데,
문제는 addEventListener
function listenMouse(m) {
m.forEach((o) => {
o.addEventListener("click", mouseClick(o));
});
이런식으로 넘겨주면, 브라우저가 이걸 읽다가 mouseclick를 실행해버린다. .. . 그래서 모든 마우스가 클릭된 상태로 시작하게 된다...
따라서 함수 실행을 미루기 위해 화살표 함수에 감싸줘야 한다.
function listenMouse(m) {
m.forEach((o) => {
o.addEventListener("click", ()=>{mouseClick(o)});
});
방법1. 파라미터 직접 넘겨주기.
이렇게 해서 마우스 클릭 이벤트에 쏙 넣어주면, 잘 작동한다.
function mouseClick(o) {
const keyCode = o.getAttribute("data-key");
const audio = document.querySelector(`audio[data-key="${keyCode}"]`);
const key = document.querySelector(`.key[data-key="${keyCode}"]`);
const keyWrap = document.querySelector(
`.key-wrap[data-key="${keyCode}"]`
);
const keyBack = document.querySelector(
`.key[data-key='${keyCode}']>div`
);
if (!audio) return;
audio.currentTime = 0;
audio.play();
keyWrap.classList.toggle("wrap-hit");
keyBack.classList.toggle("hit-back");
}
방법2. 이벤트를 넘겨주기
참고로 event 자체를 넘겨주는 아래 방법도 있는데,
function listenMouse(m) {
m.forEach((o) => {
o.addEventListener("click", (event) => {
mouseClick(event);
});
});
이렇게 이벤트를 넘겨줘서 해당 이벤트를 받은(클릭당한) 요소의 속성에서 값을 찾는건데,
console.log(event)로 찍어보니 요소의 옆구리, 위, 글씨 각각 클릭할때마다 값이 달라져서,
일관된 함수로 실행이 어려워보였다..
function mouseClick(event) {
const keyCode = event.target.getAttribute("data-key");
const audio = document.querySelector(`audio[data-key="${keyCode}"]`);
const key = document.querySelector(`.key[data-key="${keyCode}"]`);
const keyWrap = document.querySelector(
`.key-wrap[data-key="${keyCode}"]`
);
const keyBack = document.querySelector(
`.key[data-key='${keyCode}']>div`
);
if (!audio) return;
audio.currentTime = 0;
audio.play();
keyWrap.classList.toggle("wrap-hit");
keyBack.classList.toggle("hit-back");
}
방법3. this.dataset.key 사용
chatgpt가 알려줬다.
파라미터를 넘겨줄 필요도 없다.
function listenMouse(m) {
m.forEach((o) => {
o.addEventListener("click", mouseClick);
};
이렇게 멀쩡하게 이벤트만 심어준 다음,
function mouseClick() {
const keyCode = parseInt(this.dataset.key); 이런 방법도 있음!!
const audio = document.querySelector(`audio[data-key="${keyCode}"]`);
const key = document.querySelector(`.key[data-key="${keyCode}"]`);
const keyWrap = document.querySelector(
`.key-wrap[data-key="${keyCode}"]`
);
const keyBack = document.querySelector(
`.key[data-key='${keyCode}']>div`
);
if (!audio) return;
audio.currentTime = 0;
audio.play();
keyWrap.classList.toggle("wrap-hit");
keyBack.classList.toggle("hit-back");
}
이건 event와 다르게 console.log(this)를 찍어주니 항상 같은 값만 나온다.
전체 코드.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Javascript Project 30 응용</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=" />
<style>
@import url("https://fonts.googleapis.com/css2?family=Arvo:ital,wght@0,400;0,700;1,400;1,700&display=swap");
</style>
<style>
* {
font-family: "Arvo", serif;
}
body {
margin: 0;
}
.wrapper {
height: 100vh;
background-size: cover;
background-image: url("https://cdn.pixabay.com/photo/2018/05/10/11/34/concert-3387324_1280.jpg");
display: flex;
flex-wrap: wrap;
justify-content: ;
align-content: center;
}
@media (min-width: 915px) {
.wrapper {
justify-content: space-around;
}
}
.key {
height: 50px;
width: 50px;
background-color: rgba(0, 0, 0, 0.2);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
transition: all 15d0ms;
transform: rotateX(45deg) rotateZ(45deg);
transform-style: preserve-3d;
box-shadow: 5px 5px 20px -5px #444;
}
.key:before {
content: "";
position: absolute;
height: 30px;
width: 50px;
top: 50px;
left: 0px;
transform: rotateX(90deg) translateY(-15px) translateZ(15px);
background-color: rgba(0, 0, 0, 0.2);
pointer-events: none;
}
.key:after {
content: "";
position: absolute;
height: 50px;
width: 30px;
top: 0px;
right: -30px;
transform: rotateY(90deg) translateZ(-15px) translateX(15px);
border-width: 0;
border-style: solid;
border-color: #fff;
background-color: rgba(0, 0, 0, 0.2);
pointer-events: none;
}
.key .kbd {
color: white;
font-size: 20px;
}
.key-wrap {
margin: 20px;
display: block;
transition: all 200ms;
}
.wrap-hit {
transform: translateY(-20px);
}
.key-back.hit-back {
box-shadow: 0px 0px 56px 22px rgba(247, 247, 0, 1);
border: 2px solid white;
}
.sound {
color: yellow;
font-size: 10px;
}
.key-back {
position: absolute;
background-color: rgba(0, 0, 0, 0.1);
/* top: 0px;
left: 0; */
width: 50px;
height: 50px;
transform: translateZ(-29px);
box-shadow: 10px 10px 50px 0px #111;
/* z-index: 0; */
transition: all 150ms;
}
</style>
</head>
<body>
<main class="wrapper">
<div class="key-wrap" data-key="65">
<div data-key="65" class="key">
<span class="kbd">A</span>
<span class="sound">click</span>
<div class="key-back"></div>
</div>
</div>
<div data-key="83" class="key-wrap">
<div data-key="83" class="key">
<span class="kbd">S</span>
<span class="sound">click2</span>
<div class="key-back"></div>
</div>
</div>
<div data-key="68" class="key-wrap">
<div data-key="68" class="key">
<span class="kbd">D</span>
<span class="sound">keyboard</span>
<div class="key-back"></div>
</div>
</div>
<div data-key="70" class="key-wrap">
<div data-key="70" class="key">
<span class="kbd">F</span>
<span class="sound">metalic</span>
<div class="key-back"></div>
</div>
</div>
<div data-key="71" class="key-wrap">
<div data-key="71" class="key">
<span class="kbd">G</span>
<span class="sound">moneybag</span>
<div class="key-back"></div>
</div>
</div>
<div data-key="72" class="key-wrap">
<div data-key="72" class="key">
<span class="kbd">H</span>
<span class="sound">perc</span>
<div class="key-back"></div>
</div>
</div>
<div data-key="74" class="key-wrap">
<div data-key="74" class="key">
<span class="kbd">J</span>
<span class="sound">coin</span>
<div class="key-back"></div>
</div>
</div>
<div data-key="75" class="key-wrap">
<div data-key="75" class="key">
<span class="kbd">K</span>
<span class="sound">duck</span>
<div class="key-back"></div>
</div>
</div>
<div data-key="76" class="key-wrap">
<div data-key="76" class="key">
<span class="kbd">L</span>
<span class="sound">button</span>
<div class="key-back"></div>
</div>
</div>
<div data-key="186" class="key-wrap">
<div data-key="186" class="key">
<span class="kbd">;</span>
<span class="sound">bell</span>
<div class="key-back"></div>
</div>
</div>
</main>
<audio data-key="65" src="sound/click-button-140881.mp3"></audio>
<audio data-key="83" src="sound/click-button-menu-147349.mp3"></audio>
<audio data-key="68" src="sound/mech-keyboard-02-102918.mp3"></audio>
<audio data-key="70" src="sound/metalic-groan-98230.mp3"></audio>
<audio data-key="71" src="sound/money-bag-82960.mp3"></audio>
<audio data-key="72" src="sound/perc03-44836.mp3"></audio>
<audio data-key="74" src="sound/silver-quarter-4-44684.mp3"></audio>
<audio data-key="75" src="sound/single-quack-from-a-duck-14494.mp3"></audio>
<audio
data-key="76"
src="sound/tape-machine-button-press-metal-84484.mp3"
></audio>
<audio data-key="186" src="sound/thin-bell-ding-4-83140.mp3"></audio>
<script>
window.addEventListener("keydown", playSound);
function playSound(e) {
const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
const key = document.querySelector(`.key[data-key="${e.keyCode}"]`);
const keyWrap = document.querySelector(
`.key-wrap[data-key="${e.keyCode}"]`
);
const keyBack = document.querySelector(
`.key[data-key='${e.keyCode}']>div`
);
if (!audio) return;
audio.currentTime = 0;
audio.play();
keyWrap.classList.toggle("wrap-hit");
keyBack.classList.toggle("hit-back");
// console.log(e.keyCode);
}
function mouseClick() {
// const keyCode = o.getAttribute("data-key");
console.log(this);
const keyCode = parseInt(this.dataset.key);
const audio = document.querySelector(`audio[data-key="${keyCode}"]`);
const key = document.querySelector(`.key[data-key="${keyCode}"]`);
const keyWrap = document.querySelector(
`.key-wrap[data-key="${keyCode}"]`
);
const keyBack = document.querySelector(
`.key[data-key='${keyCode}']>div`
);
if (!audio) return;
audio.currentTime = 0;
audio.play();
keyWrap.classList.toggle("wrap-hit");
keyBack.classList.toggle("hit-back");
// console.log(keyCode);
}
//해당 동작이 끝나면 돌아가는 함수
function listenTransition(a) {
a.forEach((b) => {
b.addEventListener("transitionend", removeTransition);
});
}
function listenMouse(m) {
m.forEach((o) => {
o.addEventListener("click", mouseClick);
});
}
const keys = document.querySelectorAll(".key");
listenTransition(keys);
const keyBack = document.querySelectorAll(`.key > div`);
listenTransition(keyBack);
const keyWrap = document.querySelectorAll(`.key-wrap`);
listenTransition(keyWrap);
listenMouse(keyWrap);
function removeTransition(e) {
this.classList.remove("wrap-hit");
this.classList.remove("hit-back");
}
</script>
</body>
</html>
참고
이벤트 관련
https://23life.tistory.com/158
JavaScript _ addEventListener Callback함수에 파라미터 넘기기
세상 긴 제목과 그렇지 않은 내용. JavaScript에서 addEventListener를 사용할 경우... 이런 식으로 사용하는 경우가 많다. 즉 addEventListener의 첫 번째 인자로 해당 event를, 두 번째 인자로 이벤트 발생 시
23life.tistory.com
마우스 관련
https://hianna.tistory.com/492
[Javascript] 마우스 이벤트(event) 종류
마우스 이벤트의 종류를 알아보고, 각 이벤트들이 언제 어떻게 동작하는지 정리해 보았습니다. 0. 마우스 이벤트의 종류 1. click, mousedown, mouseup 2. dblclick 3. mousemove 4. mouseover, mouseout 5. mouseenter, mous
hianna.tistory.com