metronome.zip
0.12MB

 

자바스크립트로 메트로놈 구현

 

html (bootstrap)

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Metronome</title>
   <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous">
   <link rel="stylesheet" href="style.css" />
</head>
<body>
   <div class="container">
      <h3 class="text-center mt-4">Metronome</h3>
      <h1 class="text-center text-info mt-3 mb-3">60 BPM</h1>
      <input class="form-control" type="range" id="bpm" min="40" max="220" value="60" />
      <audio id="sound" src="sound.wav"></audio>
      <button class="btn btn-primary btn-block mt-4" id="startBtn">Start</button>
   </div>
   <script src="app.js"></script>
</body>
</html>

 

js

const startBtn = document.querySelector('#startBtn');
const sound = document.querySelector('#sound');
const bpm = document.querySelector('#bpm');
const title = document.querySelector('h1');
let timer = null;
let nowBpm = 60;
let isPlay = false;

bpm.addEventListener('change', (e) => {
   title.innerHTML = e.target.value + ' BPM';
   nowBpm = parseInt(e.target.value);
   if (isPlay) {
      clearInterval(timer);
      timer = setInterval(playSound, realBpm(nowBpm));
   }
});

startBtn.addEventListener('click', () => {
   if (isPlay) {
      clearInterval(timer);
      changeBtn();            
   } else {
      changeBtn();
      playSound();
      timer = setInterval(playSound, realBpm(nowBpm));            
   }
   isPlay = !isPlay;
});

function playSound() {
   sound.currentTime = 0;
   sound.play();
}

function changeBtn() {
   if(startBtn.innerHTML === 'Start') {
      startBtn.innerHTML = 'Stop';
      startBtn.classList.remove('btn-primary');
      startBtn.classList.add('btn-danger');
   } else {
      startBtn.innerHTML = 'Start';
      startBtn.classList.remove('btn-danger');
      startBtn.classList.add('btn-primary');         
   }
}

function realBpm(bpm) {
   return (60 * 1000) / bpm;
}