JS 30 Day 1 — eventListener / CSS classList 操作
在搜尋很多程式練習網站後,決定挑戰JavaScript 30 任務了!
讓我決定選擇這個挑戰的主要原因是:
- 透過實作了解更多 JS 使用技巧
- 可以先思考,再看教學影片,不會想破頭都沒答案
- 訓練英文能力
那麼就開始每日的挑戰分享啦!
專案目標:畫面上顯示九個樂器方塊,當按下鍵盤上對應的英文時,可以發出聲音並且讓對應的方塊有特效
專案成果: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的效果!