Drum Kit:線上打鼓網頁實作

Tina
5 min readJun 22, 2021

--

JS 30 Day 1 — eventListener / CSS classList 操作

Photo by Josh Sorenson on Unsplash

在搜尋很多程式練習網站後,決定挑戰JavaScript 30 任務了!

讓我決定選擇這個挑戰的主要原因是:

  1. 透過實作了解更多 JS 使用技巧
  2. 可以先思考,再看教學影片,不會想破頭都沒答案
  3. 訓練英文能力

那麼就開始每日的挑戰分享啦!

專案目標:畫面上顯示九個樂器方塊,當按下鍵盤上對應的英文時,可以發出聲音並且讓對應的方塊有特效
專案成果:
https://github.com/tinahung126/JS30-challenge/tree/master/01%20-%20JavaScript%20Drum%20Kit

分享主題:addEventListener 的特殊操作

addEventListener — transitionend event

當點擊時會讓畫面中對應的div 能有以上圖片的黃框+變大的效果,課程已經很貼心的將這個效果建立在 CSS 的 .playing class name,現在只要專注在如何在對的時間將class name加到 div 中。

<div data-key=”65" class=”key”>  <kbd>A</kbd>  <span class=”sound”>clap</span></div>

第一步:監聽鍵盤按下特定按鍵時的時候, 將 class name 加上去,這部分沒什麼問題,就是運用之前學過的classList.add加上去即可。

window.addEventListener(‘keydown’, playingSound);
function playingSound(event) {
const audio = document.querySelector(`audio
[data- key="${event.keyCode}"]`);
const key = document.querySelector(`.key[data-
key="${event.keyCode}"]`);
if (!audio) return; // 如果不是按到正確按鍵,就結束程式 key.classList.add('playing');}

接下來卻會發現,class name一加上去,卻沒有對應讓他被移除的機制,所以只要被按過,就都會有黃框的特效,就像以下的畫面

第二步:把class name 移除,這時候可能會想到利用setTimeOut的方式,來設定 0.7 秒後 remove class name,這個方法不是不行,但何不如利用 CSS transition來完成這個目標呢?

以下是他提供的 CSS 檔案(我先將比較不重要的設定拿掉),其實在 transition中也有一個 0.09 秒的 duration 這就很好的運用時機了,也是今天要講的重點!

.key { border: 0.4rem solid black; border-radius: 0.5rem; transition: all 0.09s ease;}.playing { transform: scale(1.5); border-color: #ffc600; box-shadow: 0 0 1rem #ffc600;}

這次課程中用到的方式是透過 addEventListener 完成這項目標,透過監測 transitionend 的 event來達到 setTimeOut的效果,讓transition效果結束時,觸發 removeTransition 的 function 達到效果。

const keys = Array.from(document.querySelectorAll('.key'));keys.forEach((key) => 
addEventListener('transitionend', removeTransition)
);

第三步:設定 removeTransition ,首先因為上面的 transition是設定all,就是會針對所有有變化的項目都有轉場特效,也因此這時候監測到的項目就會超級多(如下圖)

但我們只有需要針對 transform 監測,因此也需要於 function 開頭先將不必要的事件移除,這時候另一個重點來了,可以透過 propertyName 去篩選出我們要的 transform 事件後,再移除 playing 的class name

function removeTransition(event) { if (event.propertyName !== 'transform') return; event.target.classList.remove('playing');}

於是就完成了這個專案了,這次讓我接觸到原來可以透過 transitionend 的方式達到動態取消 class name的效果!

--

--

Tina
Tina

Written by Tina

前端工程師 Mix 數位行銷人

No responses yet