JavaScript 30 — Day 1
JavaScript Drum Kit
Javascript30 是一個線上的教學課程,利用三十天的時間每天實作一個簡單的 JS 作品,教學來源: https://javascript30.com/。
因緣際會看了 Alex 的頻道 (如下),受益良多,導讀看完一遍再自己寫一遍,把過程學習到的東西做一個記錄。
Day 1 實作主題:電子鼓
鍵盤上按下相對應的字母會發出鼓聲,並顯示黃色光暈的邊線樣式。
先把要做的事情畫一個大略的架構:
列出 todolist
使用者運用鍵盤事件觸發兩件事
- 開啟相對應的聲音檔
- 顯示相對應 DOM 的樣式
通常鍵盤、捲軸、螢幕旋轉等事件都是用 window 觸發,所以要先建一個從window 中按下鍵盤會觸發的 function,在此命名為 playHandler
window.addEventListener('keydown', playHandler);
KeyboardEvent 這次主要看 key、keyCode 兩個屬性,運用 css selector 選取相對應屬性,audio 要播放就用 play( )
這個方法即可
此時會遇到兩個問題:
- 按到非相對應的鍵盤會出錯,因為找不到 DOM
- 樣式(黃暈光)在按下按鍵後,不會隨著聲音停止就消失
問題 1 的解決辦法:
寫入 if 判斷,有相對應的才播放,但又會發現,重複按按鍵,聲音會累格,沒法快速重複播放,記得把時間歸零 currentTime = 0;
問題 2 的解決辦法:
要把所有的 key 用 transitionend 事件,當動畫結束時,把 css 的樣式去掉。
TransitionEvent 要注意!只要有一個以上的 transition (border, height, width,opacity….),就算監聽只有一次,仍會被反覆觸發。
先查看 console.log(e) 的資訊 我們只要抓出 propertyName: “transform” 這一個 transition,其他都不要。
在此提醒, querySelectorAll 回傳的是一個節點的集合 NodeList (不是陣列),有 length 和 forEach 的方法可以用 把每個 item 帶入 transitionend 事件監聽。
總結此實作學到的新東西及觀念:
- 為何起手式要用立即函式?
就好比你到家之後要關門,不要把東西漏出去的概念 - css 屬性選擇器
HTML lang Attribute - JQuery 的 addClass(), removeClass(), toggleClass() 同等於 JavaScript 的 classList.add( ), classList.remove( ), classList.toggle( ),只是此實作不適合用 toggle,樣式在 transitionend 動畫結束時會被觸發,所以會無止盡的出現黃光暈..變霓虹燈了 XD
- 第一次用到 HTML audio 標籤,控制播放只要加 play()即可,
補充相關連結:
audio 標籤 http://www.w3school.com.cn/tags/tag_audio.asp
video 標籤 http://www.w3school.com.cn/tags/tag_video.asp
video/audio 的 DOM https://www.w3schools.com/tags/ref_av_dom.asp
video 簡易的 js 控制 https://www.w3schools.com/html/html5_video.asp - querySelectorAll 回傳的是一個節點的集合 NodeList
類陣列的概念,有 length,forEach 等方法可以使用,但沒有 map()… - 原作者是用 Array.from 取得 querySelectorAll 的節點,將其轉換為陣列,應該是瀏覽器相容的關係,但此方法比較少用,可以參考作法。
const keys = Array.from(document.querySelectorAll(‘.key’));
- transitionend 事件
** 如果一段動畫有一個以上的屬性在跑 (width, height, transform…) transitionend 雖然只監聽一次,卻會因為 transition 有多個屬性而被重複觸發 (可以console看 e 的結果)。 - kbd — HTML 標籤,針對用戶鍵盤輸入的標籤
- 動態 DOM vs 靜態 DOM?
document.querySelectorAll 為靜態,即時新增一個 DOM,length不會跟著更新,除非重新再取值一次
document.getElementByClassName 為動態,即時新增一個 DOM,length也會跟著更新 - e.target vs e.currentTarget?
https://segmentfault.com/a/1190000011352518
https://plainnany.github.io/2017/07/06/e-target%E4%B8%8Ee-currentTarget%E7%9A%84%E5%8C%BA%E5%88%AB/ - 寫出 code 之後,建議整理一下程式碼,將 function 放置最上方,程式碼放下方,整體看起來比較整齊。
完成的實作範例:
https://chloelo.github.io/JavaScript30/01-JavaScript_Drum_Kit/index-chloe.html
原始碼:
https://github.com/chloelo/JavaScript30/tree/master/01-JavaScript_Drum_Kit
p.s. 整理筆記真的是苦差事,一下就半夜惹,但有自己寫出來又學到很多新東西很開心 : )。