Play drums using Lightning Web Component. In this article we we learn some new concepts in LWC with some interesting example.
Are you ready ? Let’s Begin !
playDrums.html
<template> <main> <section class="main-wrapper"> <div class="key-map-wrapper"> <h2>Key Mapping</h2> <ul class="key-map-list"> <template for:each={SOUND_KEYS} for:item="currentItem"> <li key={currentItem.code}> <kbd class="key-code" >{currentItem.code}</kbd> <span class="key-sound">{currentItem.sound}</span> </li> </template> </ul> </div> <h1 class="main-title"> Play drums using <br/>Lightning Web Component</h1> <div class="drum-kit-wrapper"> <img class="crash-ride crash-cymbal" ontransitionend={removeCrashRideTransition} src="https://raw.githubusercontent.com/ArunMichaelDsouza/javascript-30-course/master/src/01-javascript-drum-kit/img/crash.png" alt="Crash cymbal"> <img class="hihat-top hihat-top-cymbal" ontransitionend={removeHiHatTopTransition} src="https://raw.githubusercontent.com/ArunMichaelDsouza/javascript-30-course/master/src/01-javascript-drum-kit/img/hihat-top.png" alt="Hi Hat cymbal"> <!-- https://theasciicode.com.ar/ adding ascii on div using data-key --> <template for:each={DRUM_KEYS} for:item="currentItem"> <div key= {currentItem.key} data-key={currentItem.key} ontransitionend={removeKeyTransition} class={currentItem.class}> <kbd>{currentItem.kbd}</kbd> </div> </template> <img class="drum-kit" src="https://raw.githubusercontent.com/ArunMichaelDsouza/javascript-30-course/master/src/01-javascript-drum-kit/img/drum-kit.png" alt="Drum Kit" /> </div> </section> </main> <!-- one audio for one div--> <template for:each={SOUNDS} for:item="currentItem"> <audio key={currentItem.key} data-key={currentItem.key} src={currentItem.url}></audio> </template> </template>
playDrums.css
html,body { padding: 0; margin: 0; background-color: #fff; } .main-wrapper { margin: 30px auto 0; width: 1080px; text-align: center; } .main-title { font-family: 'Pacifico', cursive; text-align: center; font-size: 3.2em; color: #cb2026; text-shadow: 1px 1px 1px #5a0b0d; padding-bottom: 50px; } .drum-kit-wrapper { position: relative; width: 600px; margin: -100px auto 0; } .drum-kit { width: 100%; height: 520px; position: relative; } .crash-cymbal { position: absolute; top: 114px; left: 80px; transform: rotate(-7.2deg) scale(1.5); transition: all ease-in-out .042s; } .hihat-top-cymbal { position: absolute; top: 166px; right: 71px; transform: scale(1.35); z-index: 0; transition: all ease-in-out .042s; } .key { display: inline-block; transition: all ease-in-out .042s; position: absolute; background: #eaeaea; font-size: 1.5em; height: 32px; width: 32px; text-align: center; border-radius: 4px; border: 3px solid #aaa; color: #444; box-shadow: 1px 1px 1px rgba(0,0,0,.65); z-index: 2; } .key.kick { top: 355px; right: 250px; } .key.kick2 { top: 355px; right: 308px; } .key.snare { right: 145px; top: 280px; } .key.tom-high { right: 227px; top: 240px; } .key.tom-mid { left: 222px; top: 220px; } .key.tom-low { top: 320px; left: 133px; } .key.crash { top: 80px; left: 75px; } .key.ride { left: 165px; top: 87px; } .key.hihat-open { right: 165px; top: 144px; } .key.hihat-close { right: 60px; top: 150px; } .playing { transform: scale(1.12); } .key-map-wrapper { position: absolute; right: 0; top: 0; height: 700px; background: #111; width: 250px; z-index: 3; } .key-map-wrapper > h2 { color: #fff; font-family: 'Handlee', cursive; margin-bottom: 35px; border-bottom: 1px solid #fff; padding-bottom: 20px; } .key-map-list { list-style: none; color: #fff; text-align: left; } .key-map-list > li { margin-bottom: 25px; } .key-code { color: #444; background-color: #eaeaea; font-size: 1.25em; padding: 5px 10px; border-radius: 4px; border: 3px solid #aaa; } .key-sound { font-size: 1.2em; margin-left: 10px; font-family: 'Handlee', cursive; vertical-align: middle; }
playDrums.js
import { LightningElement } from 'lwc'; const SOUNDS = [ { key: "74", url:"https://raw.githubusercontent.com/ArunMichaelDsouza/javascript-30-course/master/src/01-javascript-drum-kit/sounds/snare.wav"}, { key: "66", url:"https://raw.githubusercontent.com/ArunMichaelDsouza/javascript-30-course/master/src/01-javascript-drum-kit/sounds/kick.wav" }, { key: "86", url:"https://raw.githubusercontent.com/ArunMichaelDsouza/javascript-30-course/master/src/01-javascript-drum-kit/sounds/kick.wav" }, { key: "72", url:"https://raw.githubusercontent.com/ArunMichaelDsouza/javascript-30-course/master/src/01-javascript-drum-kit/sounds/tom-high.wav" }, { key: "71", url:"https://raw.githubusercontent.com/ArunMichaelDsouza/javascript-30-course/master/src/01-javascript-drum-kit/sounds/tom-mid.wav" }, { key: "70", url:"https://raw.githubusercontent.com/ArunMichaelDsouza/javascript-30-course/master/src/01-javascript-drum-kit/sounds/tom-low.wav" }, { key: "69", url:"https://raw.githubusercontent.com/ArunMichaelDsouza/javascript-30-course/master/src/01-javascript-drum-kit/sounds/crash.wav" }, { key: "82", url:"https://raw.githubusercontent.com/ArunMichaelDsouza/javascript-30-course/master/src/01-javascript-drum-kit/sounds/ride.wav" }, { key: "73", url:"https://raw.githubusercontent.com/ArunMichaelDsouza/javascript-30-course/master/src/01-javascript-drum-kit/sounds/hihat-open.wav" }, { key: "75", url:"https://raw.githubusercontent.com/ArunMichaelDsouza/javascript-30-course/master/src/01-javascript-drum-kit/sounds/hihat-close.wav" } ] const SOUND_KEYS = [{ "code": "E", "sound": "Crash" }, { "code": "R", "sound": "Ride" }, { "code": "F", "sound": "Floor tom" }, { "code": "G", "sound": "Mid tom" }, { "code": "H", "sound": "High tom" }, { "code": "V", "sound": "B" }, { "code": "J", "sound": "Snare" }, { "code": "I", "sound": "Hi-Hat Open" }, { "code": "K", "sound": "Hi-Hat Closed" }] const DRUM_KEYS = [{ "key": "74", "class": "key snare", "kbd": "J" }, { "key": "66", "class": "key kick", "kbd": "B" }, { "key": "86", "class": "key kick2", "kbd": "V" }, { "key": "72", "class": "key tom-high", "kbd": "H" }, { "key": "71", "class": "key tom-mid", "kbd": "G" }, { "key": "70", "class": "key tom-low", "kbd": "F" }, { "key": "69", "class": "key crash", "kbd": "E" }, { "key": "82", "class": "key ride", "kbd": "R" }, { "key": "73", "class": "key hihat-open", "kbd": "I" }, { "key": "75", "class": "key hihat-close", "kbd": "K" }] export default class App extends LightningElement { playingClass = 'playing'; SOUND_KEYS= SOUND_KEYS DRUM_KEYS = DRUM_KEYS SOUNDS = SOUNDS connectedCallback(){ window.addEventListener('keydown', this.playSound); } playSound = e => { const keyCode = e.keyCode; console.log('keycode',keyCode); var keyElement = this.template.querySelector(`div[data-key="${keyCode}"]`); console.log('keyElement',keyElement); const audioElement = this.template.querySelector(`audio[data-key="${keyCode}"]`); audioElement.currentTime = 0; audioElement.play(); switch(keyCode) { case 69: case 82: this.animateCrashOrRide(); break; case 73: case 75: this.animateHiHatClosed(); break; } keyElement.classList.add(this.playingClass); }; animateCrashOrRide() { console.log('inside animatedcrash ride'); this.template.querySelector('.crash-ride').style.transform = "rotate(0deg) scale(1.5)"; }; animateHiHatClosed() { console.log('inside animateHiHatClosed'); this.template.querySelector('.hihat-top').style.top = "171px"; //hiHatTop.style.top = '171px'; }; removeCrashRideTransition = e => { console.log('inside removeCrashRideTransition'); if(e.propertyName !== 'transform') return; e.target.style.transform = 'rotate(-7.2deg) scale(1.5)'; }; removeHiHatTopTransition = e => { console.log('inside removeHiHatTopTransition'); if(e.propertyName !== 'top') return; e.target.style.top = '166px'; }; removeKeyTransition = e => { console.log('inside removeKeyTransition'); if(e.propertyName !== 'transform') return; e.target.classList.remove(this.playingClass); }; }