JavaScript 30 — Day 1

Chloe Lo
chloelo925
Published in
6 min readApr 12, 2019

JavaScript Drum Kit

Javascript30 是一個線上的教學課程,利用三十天的時間每天實作一個簡單的 JS 作品,教學來源: https://javascript30.com/

因緣際會看了 Alex 的頻道 (如下),受益良多,導讀看完一遍再自己寫一遍,把過程學習到的東西做一個記錄。

[ Alex 宅幹嘛 ] 👨‍💻 深入淺出 Javascript30 快速導覽:Day 1:JavaScript Drum Kit

Day 1 實作主題:電子鼓

鍵盤上按下相對應的字母會發出鼓聲,並顯示黃色光暈的邊線樣式。

先把要做的事情畫一個大略的架構:

列出 todolist

使用者運用鍵盤事件觸發兩件事

  1. 開啟相對應的聲音檔
  2. 顯示相對應 DOM 的樣式

通常鍵盤、捲軸、螢幕旋轉等事件都是用 window 觸發,所以要先建一個從window 中按下鍵盤會觸發的 function,在此命名為 playHandler

window.addEventListener('keydown', playHandler);

KeyboardEvent 這次主要看 key、keyCode 兩個屬性,運用 css selector 選取相對應屬性,audio 要播放就用 play( )這個方法即可

此時會遇到兩個問題:

  1. 按到非相對應的鍵盤會出錯,因為找不到 DOM
  2. 樣式(黃暈光)在按下按鍵後,不會隨著聲音停止就消失

問題 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 事件監聽。

修改後的程式碼完整版

總結此實作學到的新東西及觀念:

  1. 為何起手式要用立即函式?
    就好比你到家之後要關門,不要把東西漏出去的概念
  2. css 屬性選擇器
    HTML lang Attribute
  3. JQuery 的 addClass(), removeClass(), toggleClass() 同等於 JavaScript 的 classList.add( ), classList.remove( ), classList.toggle( ),只是此實作不適合用 toggle,樣式在 transitionend 動畫結束時會被觸發,所以會無止盡的出現黃光暈..變霓虹燈了 XD
  4. 第一次用到 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
  5. querySelectorAll 回傳的是一個節點的集合 NodeList
    類陣列的概念,有 length,forEach 等方法可以使用,但沒有 map()…
  6. 原作者是用 Array.from 取得 querySelectorAll 的節點,將其轉換為陣列,應該是瀏覽器相容的關係,但此方法比較少用,可以參考作法。
    const keys = Array.from(document.querySelectorAll(‘.key’));
  7. transitionend 事件
    ** 如果一段動畫有一個以上的屬性在跑 (width, height, transform…) transitionend 雖然只監聽一次,卻會因為 transition 有多個屬性而被重複觸發 (可以console看 e 的結果)。
  8. kbd — HTML 標籤,針對用戶鍵盤輸入的標籤
  9. 動態 DOM vs 靜態 DOM?
    document.querySelectorAll 為靜態,即時新增一個 DOM,length不會跟著更新,除非重新再取值一次
    document.getElementByClassName 為動態,即時新增一個 DOM,length也會跟著更新
  10. 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/
  11. 寫出 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. 整理筆記真的是苦差事,一下就半夜惹,但有自己寫出來又學到很多新東西很開心 : )。

--

--