mtrnm-01

by Nic Fontaine

HTML

<main>
  <div id='bpm-readout' class='bpm-readout'>60</div>
  <div class='bpm-label'>bpm</div>
  <input id='i-bpm' name='i-bpm' class='i-bpm' type='range' min='20' max='200' value='60'>
  <div id='blink-01' class='blink'></div>
  <div id='btn-start-stop' class='btn-start-stop'></div>
  <div id='demo'></div>
</main>

CSS

html {
  font-family: sans-serif;
  font-size: 1.2em;
  color: #444;
}

main {
  max-width: 400px;
  text-align: center;
  margin: 20px auto;
  border: 1px solid #ddd;
  border-radius: 5px;
  padding: 10px;
  box-sizing: border-box;
  background: #fff;
}

.bpm-readout {
  font-size: 2em;
}

.bpm-label {
  font-size: 0.9em;
  margin-bottom: 10px;
}

.i-bpm {
  width: 100%;
  margin: 0;
}

.blink {
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: #ddd;
  margin: 10px auto;
  transition: all 0.1s;
}

.blink.flash {
  background: #8FDBA2;
}

JavaScript

const gui = {
	blink01: document.getElementById('blink-01'),
  iBpm: document.getElementById('i-bpm'),
  bpmReadout: document.getElementById('bpm-readout'),
  btnSS: document.getElementById('btn-start-stop'),
  demo: document.getElementById('demo'),
  running: false,
  bpmAnimation: undefined
}

// bpm animation toggle
gui.blink01.addEventListener('click', function() {
 	if (gui.running) {
  	window.cancelAnimationFrame(gui.bpmAnimation)
    gui.running = false
  } else {
		gui.running = true
		startAnimating()  
  }
})

// bpm slider value
gui.iBpm.addEventListener('click', function() {
	gui.bpmReadout.innerHTML = this.value
  if (gui.running) {
  	window.cancelAnimationFrame(gui.bpmAnimation)
    startAnimating()
  } else {
  	window.cancelAnimationFrame(gui.bpmAnimation)
  }
})

// get slider bpm
function getBpm() {
	return gui.iBpm.value / 60
}

var stop = false
var frameCount = 0
var fps, fpsInterval, startTime, now, then, elapsed;
var bpm = 60

// bpm start rAF
function startAnimating() {
    fpsInterval = 1000 / getBpm()
    then = Date.now()
    startTime = then
    animate()
    gui.blink01.classList.add('flash')
    setTimeout(function() {
    	gui.blink01.classList.remove('flash')
    },100)
}

// bpm rAF
function animate() {
  gui.bpmAnimation = requestAnimationFrame(animate)
  now = Date.now()
  elapsed = now - then
  if (elapsed > fpsInterval) {
    then = now - (elapsed % fpsInterval)
    // animating
    gui.blink01.classList.add('flash')
    setTimeout(function() {
      gui.blink01.classList.remove('flash')
    },100)
  }
}