iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 1
1
Modern Web

新手也能懂的JS30系列 第 1

JS30-Day1-Javascript Drum Kit

JS30以及文章簡介

JS30,是由加拿大工程師Wes Bos所建立一系列課程,課程中我們可以學到很多Javascript程式語言的實際應用,例如如何操作Document中的DOM以及資料的API,對於剛踏入Javascript領域的新鮮人來說,是一個非常有趣且扎實的課題。[1]

因為本身也是剛踏入Javascript的新鮮人,希望能利用這次的比賽機會,記錄下自己的學習歷程以及心得。在此新手也能懂的JS30的文章中,將以一天一章的方式完成JS30的訓練,並針對每個章節的內容,闡述內容的思考邏輯以及方法,讓JS新手們能從這系列文章中,學習各種JS中的方法及技巧,對Javascript這個程式語言能有更進一步的認識,並希望能透過自己的經驗與想法,能激發出更多不同的火花!

Day1課題內容

JS30第一天的內容就是一個非常有趣的例子,透過結合音樂元素,創造出在頁面上打爵士鼓的體驗!
實作連結
在作者提供的範例中,我們可以發現當按下指定的按鈕時,畫面對應的地方會出現特效,且發出對應的聲音。因此可以判斷出當按下對應的按鍵時,總共發生了三件事情:

  1. 對應的區塊邊框特效
  2. 對應的字體變大及縮小
  3. 聲音的播放

加上ID

因自己本身尚未使用過data-attribute這個屬性,因此在一開始就分別給各個div元素以及audio元素加上id,方便後續利用getElementById來取的元素,內容如下:

<div data-key=65 id="key65" class="key"></div>
<div data-key=83 id="key83" class="key"></div>
<div data-key=68 id="key68" class="key"></div>
<div data-key=70 id="key70" class="key"></div>
<div data-key=71 id="key71" class="key"></div>
<div data-key=72 id="key72" class="key"></div>
<div data-key=74 id="key74" class="key"></div>
<div data-key=75 id="key75" class="key"></div>
<div data-key=76 id="key76" class="key"></div>

<audio data-key=65 id="audio65" src="sounds/clap.wav"></audio>
<audio data-key=83 id="audio83" src="sounds/hihat.wav"></audio>
<audio data-key=68 id="audio68" src="sounds/kick.wav"></audio>
<audio data-key=70 id="audio70" src="sounds/openhat.wav"></audio>
<audio data-key=71 id="audio71" src="sounds/boom.wav"></audio>
<audio data-key=72 id="audio72" src="sounds/ride.wav"></audio>
<audio data-key=74 id="audio74" src="sounds/snare.wav"></audio>
<audio data-key=75 id="audio75" src="sounds/tom.wav"></audio>
<audio data-key=76 id="audio76" src="sounds/tink.wav"></audio>  

監聽事件

首先為了在特定條件下觸發功能,我們需要給一個EventListener來監聽事件的發生,在此我們需要監聽的動作有兩項:

  1. 按下指定按鍵 -> 變更外貌及播放音樂
  2. 離開指定按鍵 -> 回復原貌及停止播放

如此一來,我們需要在頁面上監聽keydown(按下按鍵)以及keyup(放開按鍵)這兩個事件,而當事件發生時,需分別執行play以及stop這兩個函式:

window.addEventListener('keydown', play);
window.addEventListener('keyup', stop);

綁定按鍵

從範例當中,我們得知觸發事件的9個按鍵分別為A、S、D、F、G、H、J、K、L,因此當按下的按鍵必須為對應的按鍵才能觸發功能。
透過event.keyCode這個屬性,可以取得按下按鍵這個事件時,所按下按鍵的編碼。利用按鍵的編碼,我們就能判斷出按鍵是否為觸發動作的按鍵。在下面的參考連結中提供一個網站(keycode)給大家,可以快速知道每個案件對應的Keycode,十分的方便。[2]

此外,筆者在這邊有一個有趣的發現,透過event.keyCode屬性,我們只能得知目前按下按鍵,但是並無法得知目前輸入的內容。但是如果使用event.key這個屬性的話,我們就可以得知目前輸入的值,不管是大寫、小寫,甚至連注音都能讀取出來喔!

撰寫函示

按下按鍵時,頁面會執行play這個函式,離開按鍵時,則執行stop這個函式。函式中的第一件事,必須判斷按下的的是否為對應的按鍵,是的話才繼續執行後續的動作。
play函式中,在一開始判斷出對應的按鍵之後,先透過document.getElementById取得我們要動作的元素,再利用element.setAttribute()的方法,將所取得元素之class,由原本的key修改為playing,藉此來取得playing時的CSS設定。
音效的播放,使用相同方法取得對應的audio元素之後,再利用audio.play()播放其的音效內容。

而函式stop中,也使用一樣方法,將所取得元素之class,由原本的playing修改回key,並利用class間CSS設定的轉換,來產生按下按鍵時產生特效,離開按鍵時則變環原本的樣子。
音效的停止,也使用相同方法,在取得對應的audio元素之後,利用audio.load()停止播放其的音效內容。而這邊特別注意到,load()的功能並不是停止播放,而是重新加載。pause()的功能才是停止音效的播放。

function play(event) {
    //給定一變數來取得按下按鍵的keycode
    let keyboard = event.keyCode;
    //判斷式:當取得的keycode為符合的9個按鍵才會往下執行
    if (keyboard === 65 || keyboard === 83 || keyboard === 68 || keyboard ===70 || keyboard ===71 || keyboard ===72 || keyboard ===74 || keyboard ===75 || keyboard ===76) {
        //取的對應的div元素將其改為playing這個class
        document.getElementById("key" + keyboard).setAttribute('class', 'playing');
        //取的對應的audio元素並播放
        document.getElementById("audio" + keyboard).play();
     };
};

function stop(event) {
    //給定一變數來取得按下按鍵的keycode
    var keyboard = event.keyCode;
    //判斷式:當取得的keycode為符合的9個按鍵才會往下執行
    if (keyboard === 65 || keyboard === 83 || keyboard === 68 || keyboard ===70 || keyboard ===71 || keyboard ===72 || keyboard ===74 || keyboard ===75 || keyboard ===76) {
        //取的對應的div元素將其改回key這個class
        document.getElementById("key" + keyboard).setAttribute('class', 'key');
        //取的對應的audio元素並重新讀取
        document.getElementById("audio" + keyboard).load();
    };
}; 

audio小插曲

在這邊一開始寫code的時候,在函式stop中並沒有設定audio的動作,因此當按下按鍵的時候,發現到每個音效的時間長短不一,並且放開按鍵時,音效會繼續播放直到結束。後來在函式stop中嘗試加上pause()以及load(),發現後者才是我們要的效果。
pause()會將播放暫停,但是當下一次播放時,會從上一次暫停的地方繼續。load()則是將音樂重新加載,因此當我們再次按下按鍵時,便會從頭開始播放。
這邊也在下方參考資料中,提供w3school網站連結,讓大家了解音樂以及影片的一些操作method以及相關property。[3]

作者小技巧

原作者在影片當中,則是使用data attribute來取得對應的元素,可以不用額外加上id來抓取,並有效減少coding的長度。透過data attribute,我們可以添加自己需要的屬性名稱。而在此屬性名稱當中,不能包含大寫字體。此外,如果我們需要取出這個值,也有方法可以利用。[4]

//audio 元素取得
document.querySelector(`audio[data-key="${e.keyCode}"]`);
//div 元素取得
document.querySelector(`div[data-key="${e.keyCode}"]`);
//data-* attribute 值取得方法
element.dataset.key

總結

在此課題當中,我們學到以下的技能:

  1. 按鍵的事件及按鍵資料
  2. 使用data attribute來取得元素
  3. 透過class的轉換來更換CSS屬性
  4. audio的相關方法及屬性

以上是JS30第一篇帶給我的想法,如果各位讀者有些特別的點子以及coding技巧能交流的話,也歡迎留言指教,感謝您的閱讀。

參考資料

  1. javascript30
  2. Keycode
  3. w3schools Audio/Video DOM Reference
  4. MDN data attribute

下一篇
JS30-Day2-JS and CSS Clock
系列文
新手也能懂的JS3030
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言