HTML/CSS based drum set, you can play ⌨️ with the keyboard

  • Assembly kit
  • How to play?
  • Perform sound check
    • download
      • 1.CSDN points download
      • 2. Pay attention to official accounts
    • The related content

I have made the guitar and you can find it here:

JavaScript💻🤘 Make a working Guitar🎸

Guitar demos: wanghao221. Making. IO/game/js – GUI… (can’t open refresh try), tongue demonstration: wanghao221. Making. IO/game/js – dru… (Refresh if you can’t open it)

The code has been packaged and uploaded at the end of the article

Without further ado, let’s return to the instrument workshop and begin!

Assembly kit

A drum set has many parts. To build them and make them look good, I used some linear gradients and a radial gradient:

<defs>
    <radialGradient id="head" fx="26%" fy="26%">
      <stop offset="0%" style="stop-color:#f0ede6;" />
      <stop offset="100%" style="stop-color:#f5e9c9;" />
    </radialGradient>
    <radialGradient id="case" fx="30%" fy="30%">
      <stop offset="0%" style="stop-color:#82827f;" />
      <stop offset="100%" style="stop-color:#6b6b64;" />
    </radialGradient>
    <linearGradient id="caseColor">
      <stop offset="0%" style="stop-color:#6193ba;" />
      <stop offset="20%" style="stop-color:#a8c9e3;" />
      <stop offset="100%" style="stop-color:#6b6b64;" />
    </linearGradient>
    <linearGradient id="cymbal" gradientTransform="rotate(25)">
      <stop offset="0%" style="stop-color:#ede58c;" />
      <stop offset="30%" style="stop-color:#f2eec4;" />
      <stop offset="60%" style="stop-color:#f2eec4;" />
      <stop offset="100%" style="stop-color:#ede58c;" />
    </linearGradient>
  </defs>
Copy the code

Then, I added the parts of the drum set, namely the bass drum (made from a circle), snare drum and three drums (ellipse + two paths), step C c (two ellipse + one path) and crash sound (single ellipse and single path).

<! -- Hi-Tom --><path stroke-width="20" stroke="url(#case)" d="M 1000 700 1001 1200" fill="none" />
  <path stroke-width="20" stroke="url(#case)" fill="url(#caseColor)" stroke-linejoin="round" d=" M 880 700 880 820 A 1000 1900 0 0 0 1120 820 L 1120 700 Z " />
  <ellipse id="hitom" fill="url(#head)" stroke-width="20" stroke="url(#case)" cx="1000" cy="700" rx="120" ry="20" /><! -- Mid-Tom --><path stroke-width="20" stroke="url(#case)" d="M 1350 700 1351 1200" fill="none" />
  <path stroke-width="20" stroke="url(#case)" fill="url(#caseColor)" stroke-linejoin="round" d=" M 1220 700 1220 860 A 1000 1900 0 0 0 1480 860 L 1480 700 Z " />
  <ellipse id="midtom" fill="url(#head)" stroke-width="20" stroke="url(#case)" cx="1350" cy="700" rx="130" ry="20" /><! -- Bass drum --><circle id="bass" fill="url(#head)" cx="1200" cy="1200" r="270" stroke-width="20" stroke="url(#case)" /><! -- Snare drum --><path stroke-width="20" stroke="url(#case)" d="M 900 910 901 1410 780 1460 M 901 1410 1020 1460" fill="none" />
  <path stroke-width="20" stroke="url(#case)" fill="url(#caseColor)" stroke-linejoin="round" d=" M 710 900 710 1050 A 950 1700 0 0 0 1110 1050 L 1110 900 Z " />
  <ellipse id="snare" fill="url(#head)" stroke-width="20" stroke="url(#case)" cx="910" cy="900" rx="200" ry="50" /><! -- Floor tom --><path stroke-width="20" stroke="url(#case)" d="M 1700 1200 1740 1480 M 1500 1200 1450 1480" fill="none" />
  <path stroke-width="20" stroke="url(#case)" fill="url(#caseColor)" stroke-linejoin="round" d=" M 1380 1020 1380 1350 A 950 1700 0 0 0 1820 1350 L 1820 1020 Z " />
  <ellipse id="floortom" fill="url(#head)" stroke-width="20" stroke="url(#case)" cx="1600" cy="1020" rx="220" ry="60" /><! -- Hihat --><path stroke-width="20" stroke="url(#case)" d="M 500 830 500 1410 580 1460 M 500 1410 430 1460" fill="none" />
  <ellipse
    cx="500" cy="830" rx="200" ry="40"
    fill="url(#cymbal)" stroke="# 222" stroke-width="1"
  />
  <ellipse
    id="hihat-head"
    cx="500" cy="800" rx="200" ry="40"
    fill="url(#cymbal)" stroke="# 222" stroke-width="1"
  /><! -- Crash --><path stroke-width="20" stroke="url(#case)" d="M 1850 600 1851 1410" fill="none" />
  <ellipse
    id="crash"
    cx="1850" cy="600" rx="300" ry="50"
    fill="url(#cymbal)" stroke="# 222" stroke-width="1" transform="rotate(-15 1850 600)"
  />
Copy the code

The results are as follows:



It’s true that only the pedals are missing, but when I play everything on the keyboard, I still don’t need those pedals, right?

How to play?

I need to come up with some kind of button mode. I wanted this to almost look like a real drum set, so I copied the drum set layout on the keyboard:



So, basically

Hihat open: A
Hihat closed: Shift+A
Hi tom: F
Mid tom: J
Crash cymbal: O
Snare drum: B
Bass drum/kick: Space bar
Copy the code

In JS, I added an event listener to the window and analyzed the event’s key property keyDown:

let isShiftPressed = false

const hihatHead = document.querySelector('#hihat-head')
const hitom = document.querySelector('#hitom')
const midtom = document.querySelector('#midtom')
const floortom = document.querySelector('#floortom')
const snare = document.querySelector('#snare')
const crash = document.querySelector('#crash')
const bass = document.querySelector('#bass')

/**
 * Finds out which drum was played.
 * @param key
 * @returns {string|null}* /
const getInstrument = key= > {
  switch (key.toLowerCase()) {
    case 'a':
      return hihatHead
    case 'f':
      return hitom
    case 'j':
      return midtom
    case 'l':
      return floortom
    case 'b':
      return snare
    case 'o':
      return crash
    case ' ':
      return bass
  }

  return null
}

window.addEventListener('keydown'.e= > {
  if (e.key === 'Shift') {
    isShiftPressed = true
    return
  }

  const drum = getInstrument(e.key)

  if (drum === null) {
    return
  }

  // ...
})

window.addEventListener('keyup'.e= > {
  if (e.key === 'Shift') {
    isShiftPressed = false
    // ...}})Copy the code

Next, I added some animations to provide visual feedback. I used some CSS classes for this, which will be removed shortly after the timeout. I clearTimeout often do not encounter strange behavior while playing the drum:

#hihat-head.closed {
    transform: translateY(10px);
}

.played {
    transform: translateY(5px);
}
#bass.played {
    transform: scale(0.98);
    transform-origin: 1200px 1200px;
}
#crash.played {
    fill: url(#cymbal);
    transform: rotate(-20deg);
    transform-origin: 1850px 600px;
}
#hihat-head.played {
    fill: url(#cymbal);
    transform: rotate(5deg);
    transform-origin: 500px 830px;
}
Copy the code

And add and remove classes:

const timeouts = new Map(a)window.addEventListener('keydown'.e= > {
  if (e.key === 'Shift') {
    isShiftPressed = true
    hihatHead.classList.add('closed')
    return
  }

  const drum = getInstrument(e.key)
  if(! drum) {return
  }

  drum.classList.add('played')
  if (timeouts.has(drum)) {
    clearTimeout(timeouts.get(drum))
  }
  timeouts.set(drum, setTimeout(() = > {
    drum.classList.remove('played')},100))})window.addEventListener('keyup'.e= > {
  if (e.key === 'Shift') {
    isShiftPressed = false
    hihatHead.classList.remove('closed')}})Copy the code

Now play (mute) drum solo:

Perform sound check

I’ll use a MIDI font similar to guitar, but a different font: github.com/johntu/midi… The readme tells me which Note/MP3 file corresponds to which drum, so I create another map:

const sounds = new Map()
sounds.set(hihatHead, {
  open: new Audio('./sound/Bb2.mp3'),
  closed: new Audio('./sound/Gb2.mp3'),
})
sounds.set(hitom, new Audio('./sound/D3.mp3'))
sounds.set(midtom, new Audio('./sound/B2.mp3'))
sounds.set(floortom, new Audio('./sound/G2.mp3'))
sounds.set(snare, new Audio('./sound/D2.mp3'))
sounds.set(crash, new Audio('./sound/Db3.mp3'))
sounds.set(bass, new Audio('./sound/C2.mp3'))
Copy the code

Now I can adjust the event listener to actually play the sound:

window.addEventListener('keydown'.e= > {
  // ...
  const drum = getInstrument(e.key)
  // ...
  let sound = sounds.get(drum)
  if (drum === hihatHead) {
    sound = isShiftPressed ? sound.closed : sound.open
  }

  const audio = new Audio('./sound/' + sound + '.mp3')
  audio.play()

  const drum = getInstrument(e.key);
  // ..
  let sound = sounds.get(drum);
  if (drum === hihatHead) {
    sound = isShiftPressed ? sound.closed : sound.open;
  }
  sound.pause();
  sound.currentTime = 0;
  sound.play();
  // ...
})
Copy the code

A drum set that can work with a guitar! This is a live demo for you to play: wanghao221. Making. IO/game/js – dru…

download

Pay attention to the author’s public number [la la la want biu point what] reply [set of drums] free access

Pay attention to support it, I will continue to update similar free fun H5 games, Java games, fun, practical projects and software and so on

The related content

And finally, don’t forget ❤ or 📑