01 - JavaScript Drum Kit 俗話說的好,一天一蘋果,醫生遠離我 一天一JS,What the f*ck JavaScript? small steps every day - 記錄著新手村日記
Drum Kit 完成目標 一個鍵盤爵士鼓
index_START.html html 的整體結構如下所示, class="keys"
包住九個 data-key="number" class="key"
的 div
,內部又有用 kbd
和 span
標籤包住的文字,下方有 audio
標籤包 data-key="number" src="音檔"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > JS Drum Kit</title > <link rel ="stylesheet" href ="style.css" > </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
data-key
data-* 屬性是 HTML5 中的新屬性,後面的名稱我們可以自己定義,舉例來說:
1 2 3 4 <div id ="block" > <div class ="block1" data-myid ="no1" > 請點我,我是編號一</div > <div class ="block1" data-myid ="no200" > 請點我,我是編號二百</div > </div >
利用 jQuery 取出 data-myid
的值
1 2 3 $('#block .block1' ).click(function ( ) { alert($(this ).attr("data-myid" )); });
kbd
kbd 標籤表示使用者輸入,它將產生一個行内元素(inline),舉例來說:
1 2 3 <p > Type the following in the Run dialog: <kbd > cmd</kbd > <br /> Then click the OK button.</p > <p > Save the document by pressing <kbd > Ctrl</kbd > + <kbd > S</kbd > </p >
執行結果
1 2 3 4 Type the following in the Run dialog: cmd Then click the OK button. Save the document by pressing Ctrl + S
data-key=”number” 中的 number 該為何?
每個鍵盤都分別有一個對應的 event.key
、event.location
、event.which
、event.code
,以字母A為例子,分別是A、0、65、KeyA
可以在這個網站中試試看:http://keycode.info/
CSS 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 html { font-size : 10px ; background : url (http://i.imgur.com/b9r5sEL.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 : .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 ; }kbd { display : block; font-size : 4rem ; }.sound { font-size : 1.2rem ; text-transform : uppercase; letter-spacing : .1rem ; color : #ffc600 ; }
JS - step by step 首先,先來驗證一下 html 中我們要抓的 data-key
的值,透過 EventTarget.addEventListener()
印出使用者按下按鍵後的 KeyboardEvent
EventTarget.addEventListener():https://ubin.io/SpgtjL
1 2 3 4 5 <script > window .addEventListener('keydown' ,function (e ) { console .log(e) })</script >
透過 querySelector
抓取按下字母,並可以對應出 HTML 中 div 與 audio 的 data-key="number"
,如果沒有這個值,console 會印出 null
document.querySelector():https://ubin.io/ehKgvQ
1 2 3 4 5 6 7 8 <script > window .addEventListener('keydown' ,function (e ) { const audio = document .querySelector(`audio[data-key="${e.keyCode} "]` ) console .log(audio) const key = document .querySelector(`div[data-key="${e.keyCode} "]` ) console .log(key) })</script >
如果 audio 存在,只需要 audio.play()
就可以播放音樂了!不過考量讓聲音重複播放的話,就必須將現在的時間設為 0,也就是下方的 audio.currentTime=0
,按住字母A來發射機關槍聲音吧w
1 2 3 4 5 6 7 8 9 10 <script > window .addEventListener('keydown' ,function (e ) { const audio = document .querySelector(`audio[data-key="${e.keyCode} "]` ) if(audio){ audio.currentTime = 0 audio.play() } const key = document .querySelector(`div[data-key="${e.keyCode} "]` ) })</script >
同理,字母方塊在使用者按下按鍵也要給加 class (黃色陰影、放大1.1倍),key.classList.add('playing')
如同 Jquery 的.addClass()
,不過有新增就要有移除,現在黃色的特效會一直卡住沒有變回原本的樣子
1 2 3 4 5 6 7 8 9 10 11 12 13 <script > window .addEventListener('keydown' ,function (e ) { const audio = document .querySelector(`audio[data-key="${e.keyCode} "]` ) if(audio){ audio.currentTime = 0 audio.play() } const key = document .querySelector(`div[data-key="${e.keyCode} "]` ) if(key){ key.classList.add('playing' ) } })</script >
先抓出所以 class 中有 .key 透過 forEach 讓每個 .key 讀出來,並呼叫 removeTransition
方法
document.querySelectorAll():https://ubin.io/cVr2Ua
1 2 3 4 5 6 7 8 9 10 11 12 <script > window .addEventListener('keydown' ,function (e ) { const keys = document .querySelectorAll('.key' ) keys.forEach(function (key ) { key.addEventListener('transitionend' , removeTransition) }) function removeTransition (e ) { console .log(e) } })</script >
console 中每按一下按鍵就會觸發六個屬性:border-left-color
、border-right-color
、border-top-color
、transfrom
、box-shadow
、border-bottom-color
,除了transform
是動畫之外,其他是黃色陰影的部分。因此如果 propertyName === 'transform'
的話,我們要移除 playing
這個 class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <script > window .addEventListener('keydown' ,function (e ) { const keys = document .querySelectorAll('.key' ) keys.forEach(function (key ) { key.addEventListener('transitionend' , removeTransition) }) function removeTransition (e ) { if (e.propertyName === 'transform' ){ e.currentTarget.classList.remove('playing' ) } } })</script >
就大功告成啦!來創作一首曲子吧w
JS - Final 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <script > window .addEventListener('keydown' ,function (e ) { const audio = document .querySelector(`audio[data-key="${e.keyCode} "]` ) if(audio){ audio.currentTime = 0 audio.play() } const key = document .querySelector(`div[data-key="${e.keyCode} "]` ) if(key){ key.classList.add('playing' ) } const keys = document .querySelectorAll('.key' ) keys.forEach(function (key ) { key.addEventListener('transitionend' , removeTransition) }) function removeTransition (e ) { if (e.propertyName === 'transform' ){ e.currentTarget.classList.remove('playing' ) } } })</script >
本次範例程式碼原作者來源:https://reurl.cc/Rd6bLn