iT邦幫忙

2024 iThome 鐵人賽

DAY 1
0

Day01 是實作用鍵盤模擬打鼓的題目,當使用者按下對應的按鍵,就會播放對應的鼓聲,以下就讓我們來製作 React 的版本ㄅ (之後每天的示範樣式都會使用 TailwindCSS)

資料對應表

  • 首先,建立 1 個物件陣列 drumMap,用來存放每個按鍵對應的聲音檔名:
const drumMap = [
  { key: "A", code: 65, sound: "clap" },
  { key: "S", code: 83, sound: "hihat" },
  { key: "D", code: 68, sound: "kick" },
  { key: "F", code: 70, sound: "openhat" },
  { key: "G", code: 71, sound: "boom" },
  { key: "H", code: 72, sound: "ride" },
  { key: "J", code: 74, sound: "snare" },
  { key: "K", code: 75, sound: "tom" },
  { key: "L", code: 76, sound: "tink" },
];

鍵盤事件

  • 接著,我們可以利用 onKeyDowntabIndex 屬性,來讓元素聚焦並處理鍵盤事件。當使用者按下按鍵時,handleKeyDown 函式會被觸發:
const handleKeyDown = (e: { key: string }) => {
  const targetKey = drumMap.find((drum) => drum.key === e.key.toUpperCase());
  if (!targetKey) {
    return;
  }
  playDrum(targetKey);
};

播放音效

  • useState 來管理目前按下的按鍵,同時用來處理讓畫面有亮燈的效果。當使用者點擊或按下對應的按鍵時,playDrum 函式會被觸發,播放對應的鼓聲:
const [activeKey, setActiveKey] = useState<string>("");

const playDrum = (targetKey: { key: string; sound: string }) => {
  const audio = new Audio(
    `https://github.com/wesbos/JavaScript30/raw/master/01%20-%20JavaScript%20Drum%20Kit/sounds/${targetKey.sound}.wav`
  );
  audio.currentTime = 0;
  audio.play();
  
  setActiveKey(targetKey.key);
};

清空狀態

  • 當按鍵離開時,我們需要把狀態清空,讓亮燈效果消失:
const handleClear = () => {
  setActiveKey("");
};

畫面結構

  • 最後,利用 JSX 語法來顯示整個畫面的結構:
return (
  <main className="bg-[url('https://raw.githubusercontent.com/wesbos/JavaScript30/master/01%20-%20JavaScript%20Drum%20Kit/background.jpg')] bg-cover bg-center h-screen w-full">
    <div
      className="flex flex-wrap justify-center items-center min-h-screen gap-2"
      tabIndex={0}
      onKeyDown={handleKeyDown}
      onKeyUp={handleClear}
    >
      {drumMap.map((drum) => (
        <div
          key={drum.key}
          onClick={() => playDrum(drum)}
          onMouseLeave={handleClear}
          className={`${
            activeKey === drum.key
              ? "border-yellow-500 shadow-2xl transform scale-110"
              : "border-black"
          } w-20 h-20 flex flex-col justify-center items-center bg-black bg-opacity-60 text-white rounded-lg border-4 transition-all hover:border-yellow-500 hover:shadow-2xl hover:transform hover:scale-110 hover:cursor-pointer`}
        >
          <kbd className="text-2xl">{drum.key}</kbd>
          <p className="text-sm text-yellow-500">
            {drum.sound.toUpperCase()}
          </p>
        </div>
      ))}
    </div>
  </main>
);

DEMO

https://codesandbox.io/p/devbox/prod-microservice-289gyc

總結

  • 使用 new Audio() 建立聲音物件

  • 設定 audio.currentTime = 0 可以讓聲音從頭播放

  • 利用 onKeyDownonKeyUponMouseLeave 等事件來處理使用者互動

  • 在 TailwindCSS 中,可以使用 bg-[url('...')] 的語法來設定背景圖片

bg-[url('https://raw.githubusercontent.com/wesbos/JavaScript30/master/01%20-%20JavaScript%20Drum%20Kit/background.jpg')]

下一篇
[Day02]_Clock
系列文
React30——用 React 探索 JavaScript30 的魅力30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
brownrice
iT邦新手 4 級 ‧ 2024-09-18 12:42:06

加油~~

ayao iT邦新手 5 級 ‧ 2024-09-20 20:50:41 檢舉

感謝,一起加油

我要留言

立即登入留言