๐ ์๊ตฌ์ฌํญ
- ํค๋ณด๋๋ฅผ ๋๋ ์ ๋, ๋๋ฆฐ ํค์์ ํด๋น ์ค๋์ค ์๋ฆฌ๊ฐ ์ฌ์๋๊ฒ ํ๋ค.
- ๋๋ฆฐ ํค ์์์ playing ํด๋์ค๋ฅผ ์ถ๊ฐํ์ฌ ํน์ css๋ฅผ ์ ์ฉํ๋ค.
- ๋ชจ๋ ์ด๋ฒคํธ๊ฐ ๋๋๋ฉด, playing ํด๋์ค๋ฅผ ์ ๊ฑฐํ์ฌ ์ด๊ธฐ ์ํ๋ก ๋ณต๊ตฌํ๋ค.
โจ ๊ฒฐ๊ณผํ๋ฉด
๐ป ์์ค์ฝ๋
document.addEventListener("keydown", playSound); // ํค ๋๋ ธ์ ๋
const keys = document.querySelectorAll(".key"); // ์ด๋ฒคํธ ๋๋ฌ์ ๋
keys.forEach((key) => key.addEventListener("transitionend", removePressed));
// Key๊ฐ ๋๋ ธ์ ๋ ๋์ํ๋ ํจ์
function playSound(e) {
const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
const key = document.querySelector(`.key[data-key="${e.keyCode}"]`);
if (key == null || audio == null) {
// ๋๋ฆฐ key ๋๋ audio๊ฐ null ์ด๋ฉด ์๋ฌด๊ฒ๋ ํ์ง ์๋๋ค.
return;
}
audio.currentTime = 0; // ์ฌ์ ์ง์ ์ 0์ผ๋ก ์ค์ ํ์ฌ ๋๋ฅผ ๋๋ง๋ค ์ฌ์ ์ง์ ์ด๊ธฐํ
audio.play();
key.classList.add("playing");
}
// ์ด๋ฒคํธ๊ฐ ๋๋๋ฉด ์คํ๋ ํจ์
function removePressed(e) {
if (e.propertyName != "transform") return; // transform์ด ์๋ border, shadow ๋ฑ์ ๊ฒฝ์ฐ์๋ ๋ฌด์
// console.log(e.propertyName); // ์ด ๋, transform์์ฑ๋ง ์ถ๋ ฅ๋๋ค.
this.classList.remove("playing");
}
๐ TIL
data-*
HTML5๋ถํฐ ์ถ๊ฐ๋ ์์ฑ์ผ๋ก, HTML ์์์ ๊ฐ๋จํ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ์ ์๋๋ก ํด์ค๋ค. data-* ์์ฑ์ ์ด๋ฆ ์์ฑ ๊ท์น๊ณผ ๋ฌธ๋ฒ์ ๋ค์๊ณผ ๊ฐ๋ค.
- ๋์๋ฌธ์ ์ฌ๋ถ์ ์๊ด์์ด xml๋ก ์์ํ๋ฉด ์๋๋ค.
- ์ธ๋ฏธ์ฝ๋ก (U+003A)์ ํฌํจํด์๋ ์๋๋ค.
- ๋๋ฌธ์๋ฅผ ํฌํจํด์๋ ์๋๋ค.
-
<article id="electriccars" data-columns="3" data-index-number="12314" data-parent="cars"> ... </article>
JavaScript์์ data-*์ ์ ์๋ ์์ฑ ๊ฐ๋ค์ ์ฝ๋ ๋ฐฉ๋ฒ์, dataset ์์ฑ์ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค. ์ด ๋, HTML์์ ๋์(-)๋ก ๊ตฌ๋ถ๋์๋ ์ด๋ฆ ๋ฌธ์๋ camelCase๋ก ๋ณํ๋๋ค.
var article = document.getElementById('electriccars');
article.dataset.columns // "3"
article.dataset.indexNumber // "12314"
article.dataset.parent // "cars"
Drum Kit ์์ค์ฝ๋์ data-* ์ ๊ทผ ๋ฐฉ์์ ์ดํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
const key = document.querySelector(`.key[data-key="${e.keyCode}"]`);
์ฌ๊ธฐ์์๋ ๋ฐฑํฑ(`)์ ํตํด ์ ๊ทผํ ๊ฒ์ ๋ณผ ์ ์๋ค. audio์ key๋ฅผ ์์๋ก ์ ์ธํ ํ, audio๋ <audio>ํ๊ทธ ์ค์์ data-key๊ฐ ๋๋ฆฐ ํค๋ณด๋์ KeyCode์ธ ๊ฒ์, key๋ ํด๋์ค๋ช ์ด key์ธ ๊ฒ๋ค ์ค์์ data-key๊ฐ ๋๋ฆฐ ํค๋ณด๋์ KeyCode์ธ ๊ฒ์ ๊ฐ์ ธ์จ๋ค.
audio
HTML5๋ถํฐ ๋์ ๋ <audio> ํ๊ทธ๋ ๋ฌธ์์ ์๋ฆฌ ์ฝํ ์ธ ๋ฅผ ํฌํจํ ๋ ์ฌ์ฉํ๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก <audio src="ํ์ผ๊ฒฝ๋ก">๋ก ์ ์ธํ๊ณ , controls, autoplay, loop ๋ฑ์ ๋ค์ํ ์์ฑ์ ์ถ๊ฐํ ์ ์๋ค. Drum Kit์ HTML ์์ค์ฝ๋์์๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑ๋์ด ์๋ค.
<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>
JS์์์ ์ ๊ทผ์ ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก ํ๋ค.
const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
audio.currentTime = 0;
audio.play();
audio ์์๋ฅผ ํตํด querySelector๋ก ๋๋ฆฐ KeyCode๋ฅผ ๊ฐ์ง <audio> ํ๊ทธ๋ก ์ ๊ทผํ ํ, play() ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ ์์ ์ ์ฌ์ํ๋ค. ๊ทธ๋ฐ๋ฐ, ๋จ์ํ audio.play(); ๋ง ์ ์ธ์ ํ๋ฉด ์ด์ ์ ์ฌ์ํ๋ ์ง์ ์ด ์ ์ฉ๋์ด ๋ช ์ด๊ฐ์ ํ ์ด ๋ฐ์ํ๋ค. ๊ทธ๋์ currentTime ์์ฑ์ ์ด์ฉํ์ฌ ์ฌ์ ์ง์ ์ ์ด๊ธฐํ ํด์ค๋ค.
์์ฑ | ์ค๋ช |
autoplay | ๋ธ๋ผ์ฐ์ ๊ฐ load๋ ๋ ์๋ ์ฌ์ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๋ค. boolean ๊ฐ์ ๊ฐ๋๋ค. |
currentTime | ์ฌ์ ์ง์ ์ ์ค์ ํ๋ค. ์ด ๋จ์๋ก, 0์ด๋ฉด ์ฒ์๋ถํฐ ์ฌ์ํ๋ค. |
loop | ๋ฐ๋ณต ์ฌ์ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๋ค. boolean ๊ฐ์ ๊ฐ๋๋ค. |
src | audio์ ๊ฒฝ๋ก(URL)๋ฅผ ์ค์ ํ๋ค. |
volume | ์๋์ ์ง์ ํ๋ค. 0.0~1.0 ์ฌ์ด์ ๊ฐ์ผ๋ก ์ง์ ํ ์ ์๋ค. |
transitionend
transitionend๋ CSS์ transition์ด ์๋ฃ๋ ์ดํ์ ๋ฐ์ํ๋ ์ด๋ฒคํธ๋ก, transition๊ณผ ํจ๊ป ์ฌ์ฉ๋๋ ํจ์์ด๋ค.
const transition = document.querySelector('.transition');
transition.addEventListener('transitionend', () => {
console.log('Transition ended');
});
์์ ๊ฐ์ด addEventListener๋ฅผ ํตํด transitionend์ด๋ฒคํธ๋ฅผ ๋ฑ๋กํ์ฌ ์ฌ์ฉํ ์ ์๋ค. Drum Kit์์๋ ํค๊ฐ ๋๋ ธ์ ๋ key.classList.add("playing")์ ํตํด ํด๋น ์์์ playing ํด๋์ค๋ฅผ ์ถ๊ฐํด์ค๋ค. ๊ทธ๋ฐ๋ฐ transitionend๋ฅผ ํ์ง ์์ผ๋ฉด, ํค๊ฐ ๋๋ฆฐ ํจ๊ณผ๊ฐ ์ง์๋๋ค. ๊ทธ๋์ ์ฐ๋ฆฌ๋ ํด๋น ์ด๋ฒคํธ๊ฐ ๋๋๋ฉด, playing ํด๋์ค๋ฅผ remove ํด์ ์ํ๋ฅผ ์์๋ณต๊ตฌ ์์ผ์ค์ผ ํ๋ค. Drum Kit ์์ค์ฝ๋์์๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ๋ค.
const keys = document.querySelectorAll(".key");
keys.forEach((key) => key.addEventListener("transitionend", removePressed));
function removePressed(e) {
if (e.propertyName != "transform") return;
this.classList.remove("playing");
}
keys ์์๋ฅผ ์ ์ธํ์ฌ key ํด๋์ค๋ฅผ ๊ฐ์ง ๋ชจ๋ ์์๋ค์ ๊ฐ์ ธ์จ๋ค. querySelectorAll()์ ์ด์ฉํด์ ๊ฐ์ ธ์๋๋ฐ, querySelectorAll()์ ์กฐ๊ฑด์ ๋ง๋ ๋ชจ๋ ์์๋ค์ NodeList๋ก ๋ฐํํ๋ค. ๊ทธ๋์ keys.addEventListener์ ๊ฐ์ด ์ ์ธํ๋ฉด ๋ชจ๋ ์์๋ค์ ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ์ถ๊ฐํ ์ ์๋ค. ๊ทธ๋์ forEach๋ฅผ ์ฌ์ฉํด์ ๋ชจ๋ ์์๋ค์ ์ํํ๋ฉฐ ๊ฐ๊ฐ์ ์์๋ค์ ์ด๋ฒคํธ๋ฅผ ๊ฑธ์ด์ค์ผ ํ๋ค.
๊ทธ๋ฆฌ๊ณ ์คํ ์๊ฐ์ด ๊ฐ์ฅ ๊ธด transform๋ง ๋ฝ์์ ์๊ฐ ๋๋๋ฉด ๋ชจ๋ transition ์์๋ค์ด ์๋์ผ๋ก ๋๋ ์ ์๋๋ก ํด ์ฃผ๋ฉด ๋๋ค. propertyName์์ฑ์ ํ์ฉํด์ transform์ ๋ฝ์๋ธ ํ, ํด๋น ์ด๋ฒคํธ๊ฐ ๋๋๋ฉด classList.remove("playing")์ ํตํด playing ํด๋์ค๋ฅผ ์ ๊ฑฐํ์ฌ CSS ์์๋ฅผ ์ฒ์์ผ๋ก ์ด๊ธฐํํ๋ฉด ๋๋ค.
(์์์์ "this"๋ always equal to the whatever got called against it. ์ด๋ผ๊ณ ํ๋ค. ๋์ค์ this์ ๋ํด์๋ ํ ๋ฒ ๊ณต๋ถํ๊ณ ์ ๋ฆฌํด์ผ๊ฒ ๋ค.)
๐ ์ฐธ๊ณ
youtube Wes Bos
https://www.youtube.com/watch?v=VuN8qwZoego&list=PLu8EoSxDXHP6CGK4YVJhL_VWetA865GOH
https://developer.mozilla.org/ko/docs/Learn/HTML/Howto/Use_data_attributes
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/transitionend_event