Hamburger Icon
  • Labs icon Lab
  • Core Tech
Labs

Guided: Build a Drum Machine with Vue

In this guided lab, learners will use the Vue.js framework to construct an interactive drum machine. This application will enable users to create unique rhythms by setting different drum elements such as the kick, snare, and hihat. Each drum track is visually represented, and users can easily toggle beats between active ('x') and inactive ('-') states. The application provides controls to adjust the BPM (beats per minute) and play or stop the drum sequences. To produce the actual drum sounds, we'll be utilizing HTML audio samples.

Labs

Path Info

Level
Clock icon Intermediate
Duration
Clock icon 40m
Published
Clock icon Oct 09, 2023

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Table of Contents

  1. Challenge

    Overview

    In this guided lab, you will use the Vue.js framework to construct an interactive drum machine. This application will enable users to create unique rhythms by setting different drum elements such as the kick, snare, and hihat. Each drum track is visually represented, and users can easily toggle beats between active ('x') and inactive ('-') states. The application provides controls to adjust the BPM (beats per minute) and play or stop the drum sequences. To produce the actual drum sounds, we'll be utilizing HTML audio samples.

    Using the Drum Machine

    1. Click the Run button in the bottom right of the Terminal and then visit the Web Browser tab. This provides a real-time preview of your drum machine as you work on it.

    2. Adjust BPM: Locate the BPM input field and try setting different values.

    3. Toggling Beats: On the visual representation of the tracks, click on any beat to toggle its state.

    4. Control Playback: Use the Start and Stop buttons to initiate or halt the drum loop playback.

    Tips:

    • To ensure the changes in rhythm patterns are audibly reflected, stop the playback before modifying a beat pattern and then restart it.

    Happy coding!

  2. Challenge

    Creating the Vue Template

    Task: Generate Drum Track Divs.

    Iterate over the trackList and create a div for each track.

    👣 Steps
    1. Use the v-for directive to loop over trackList.
    2. Bind each track's name to the key attribute to ensure uniqueness.
    3. Assign the class track to each generated div.
    🔍 Hint

    In Vue, the v-for directive allows you to iterate over items in an array and render a block of code for each item.

    🔑 Solution
    <div v-for="track in trackList" :key="track.name" class="track">
    </div>
    

    Task: Display the Track Label.

    Display the capitalized name of the drum track followed by a colon.

    👣 Steps
    1. Inside the div from the previous task, use the {{ }} syntax to bind and display the track's name.
    2. Use JavaScript string methods to capitalize the first letter of the name.
    3. Follow the name with a colon.
    🔍 Hint

    You can capitalize the first character of a string and add the rest of the string using string manipulation methods like charAt() and slice().

    🔑 Solution
    <span>{{ track.name.charAt(0).toUpperCase() + track.name.slice(1) }}:</span>
    

    Task: Generate Beat Divs for Each Drum Track.

    For every drum track, iterate over its pattern and create a div for each beat.

    👣 Steps
    1. Inside the main track div, use another v-for to loop over track.pattern.
    2. Bind the index of each beat to the key attribute.
    3. Conditionally assign the active class if the beat equals 'x' using the object-syntax for class bindings.
    🔍 Hint

    Vue allows nested loops using v-for. For conditional class bindings, Vue's class binding syntax { 'class-name': condition } can be useful.

    🔑 Solution
    <div v-for="(beat, index) in track.pattern" 
         :key="index"
         :class="['step', { 'active': beat === 'x' }]"
         @click="toggleStep(track.name, index)">
    </div>
    

    Task: Add BPM Input.

    Provide an input field for users to set the BPM (Beats Per Minute).

    👣 Steps
    1. Use the v-model directive to bind the BPM value.
    2. Specify the input type as number.
    3. Assign an ID to the input for possible further referencing.
    🔍 Hint

    v-model in Vue provides two-way data binding on an input form control.

    🔑 Solution
    <input v-model="bpm" type="number" id="bpmInput" />
    

    Task: Add Control Buttons.

    Add buttons to start and stop the drum machine.

    👣 Steps
    1. Create two button elements.
    2. Assign click events using the @click directive to call startDrumMachine and stopDrumMachine methods respectively.
    🔍 Hint

    In Vue, the @click directive is a shorthand for v-on:click, which is used to listen to DOM events and execute some JavaScript when they're triggered.

    🔑 Solution
    <button @click="startDrumMachine">Start</button>
    <button @click="stopDrumMachine">Stop</button>
    

  3. Challenge

    Create the Drum Machine Functionality

    Task: Initialize Component Data.

    Set up the initial data properties for the Vue component.

    👣 Steps
    1. Declare a data function that returns an object.
    2. Initialize drumInterval to null. This will store the interval reference for the drum machine.
    3. Set up a trackList array that contains objects with information on each drum track.
    4. Initialize bpm (Beats Per Minute) to 120.
    🔍 Hint

    In a Vue component, the data function returns an object that holds the initial values for the properties.

    🔑 Solution
    data() {
      return {
        drumInterval: null,
        trackList: [
          { name: 'kick', pattern: 'x-------x-------', sample: new Audio('/kick.wav') },
          { name: 'snare', pattern: '----x-------x---', sample: new Audio('/snare.wav') },
          { name: 'hihat', pattern: 'x-x-x-x-x-x-x-x-', sample: new Audio('/hihat.wav') }
        ],
        bpm: 120
      };
    }
    

    Task: Implement the toggleStep Method.

    Create a method to toggle a step (from '-' to 'x' or vice versa) in the pattern of a specific drum track.

    👣 Steps
    1. Declare a toggleStep method that accepts trackName and index as parameters.
    2. Find the specified track in trackList.
    3. Modify the track's pattern at the specified index.
    🔍 Hint

    Use the find method on arrays to locate the desired track based on its name.

    🔑 Solution
    toggleStep(trackName, index) {
      let track = this.trackList.find(t => t.name === trackName);
      let pattern = track.pattern;
      let active = pattern[index] === 'x' ? '-' : 'x';
      track.pattern = `${pattern.slice(0, index)}${active}${pattern.slice(index + 1)}`;
    }
    

    Task: Implement the startDrumMachine Method.

    Create a method to start playing the drum machine.

    👣 Steps
    1. First, stop any running drum machine using the stopDrumMachine method.
    2. Calculate the time between each drum beat using the bpm.
    3. Use setInterval to loop through each drum track and play the associated sample if its pattern has an 'x' at the current step.
    4. Update the step counter and loop it back to the start when it reaches the end.
    🔍 Hint

    Remember to use this to refer to the component's data and methods within the methods.

    🔑 Solution
    startDrumMachine() {
      this.stopDrumMachine();
    
      const step_time = 60000 / this.bpm;
    
      let step = 0;
      this.drumInterval = setInterval(() => {
        this.trackList.forEach(track => {
          if (track.pattern[step] === 'x') {
            track.sample.currentTime = 0;
            track.sample.play();
          }
        });
        step = (step + 1) % this.trackList[0].pattern.length;
      }, step_time);
    }
    

    Task: Implement the stopDrumMachine Method.

    Create a method to stop the drum machine.

    👣 Steps
    1. Check if drumInterval is not null.
    2. Use clearInterval to stop the currently running drum machine.
    3. Reset drumInterval to null.
    🔍 Hint

    clearInterval is a built-in JavaScript function that stops an interval started by setInterval.

    🔑 Solution
    stopDrumMachine() {
      if (this.drumInterval) {
        clearInterval(this.drumInterval);
        this.drumInterval = null;
      }
    }
    

Danny Sullivan is a former special education teacher and professional baseball player that moved into software development in 2014. He’s experienced with Ruby, Python and JavaScript ecosystems, but enjoys Ruby most for its user friendliness and rapid prototyping capabilities.

What's a lab?

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Provided environment for hands-on practice

We will provide the credentials and environment necessary for you to practice right within your browser.

Guided walkthrough

Follow along with the author’s guided walkthrough and build something new in your provided environment!

Did you know?

On average, you retain 75% more of your learning if you get time for practice.