Building a Single Song Player

Part 3 of 7 in AmplitudeJS: From the Ground Up
Dan Pastori avatar
Dan Pastori August 30th, 2018

So, let’s start with a very simple player, a single song player. For this tutorial, I will be building the example player here: amplitudejs/examples/single-song at master · 521dimensions/amplitudejs · GitHub. All the code is available to download but I’ll be walking through the basics as an introduction on how to use AmplitudeJS and play a single song in your browser.

Pre-Requisites

Before we start building our player, we need to have a few assets in order:

  1. The newest version of AmplitudeJS here: GitHub – 521dimensions/amplitudejs: Amplitude.js is the HTML5 Audio Player for the modern era. No dependencies required.
  2. A song you want to play (preferably in an MP3 Format)
  3. An organized directory you can open in a web browser. You shouldn’t need a web server since there’s no server side code.

If you have a design for your player already, you can follow along with the basics, otherwise feel free to grab the files from the example player as that’s what we will be using to step through.

What We Will Touch On

  • Getting AmplitudeJS initialized
  • Play/Pause Button
  • Song Meta Data
  • Song Progress Bar
  • Time Meta Data

Getting Started

With any web development, I like to lay out my folder structure right away so as I build I have places for all of my assets.

For this player, I’d open your working directory and make the following files and folders:

  • /index.html
  • /css
  • /js
  • /img

If you are doing SASS compiling or any other JS compiling, you might want to add a /resources directory and add all of your components in there. In the example player we DO use SASS, but that’s outside the scope of this tutorial. We will be walking through the mindset of using AmplitudeJS for building a single song player.

As for JS, if you are following along with the example player, I have foundation and jQuery included. AmplitudeJS is not dependent on any 3rd party library so these are not required for any player. I use foundation for just page layout and jQuery for any animation functions.

Structuring Your Player

To start off, set up your index.html file like this:

<!DOCTYPE html>
<html>
  <head>
    <title>AmplitudeJS Single Song Example</title>

    <!-- Foundation Framework CSS -->
    <link rel="stylesheet" href="css/foundation.min.css">

    <!-- Include font -->
    <link href="https://fonts.googleapis.com/css?family=Lato:400,400i" rel="stylesheet">


        <!-- Include Amplitude JS -->
        <script type="text/javascript" src="js/amplitude.js"></script>

    <!-- Foundation jQuery and Functions -->
    <script type="text/javascript" src="js/jquery.js"></script>
    <script type="text/javascript" src="js/foundation.min.js"></script>

        <!--
            Include UX functions JS

            NOTE: These are for handling things outside of the scope of AmplitudeJS
        -->
        <script type="text/javascript" src="js/functions.js"></script>

        <!-- Include Style Sheet -->
    <link rel="stylesheet" type="text/css" href="css/app.css"/>
  </head>
  <body>
    <div class="grid-x grid-padding-x">
      <div class="large-12 medium-12 small-12 cell">

      </div>
    </div>
  </body>
</html>

A few things to notice here, we included foundation: The most advanced responsive front-end framework in the world. | Foundation like I mentioned, this is only for layout and helps design the player.

I also included a Google Font which makes the player look good. You can include any other styles or fonts if needed.

Next, I add a player container which is simply a <div> element that we will be structuring to make our player.

...
  <div id="single-song-player">

  </div>
...

This is not an AmplitudeJS element it’s simply a container for the player that we are building. Inside of this element will contain a few AmplitudeJS specific elements.

Adding Album Art

This is our first encounter with an AmplitudeJS specific element. We will be adding our album art image to the player. To do this, right inside of the id=“single-song-player” element, add the following:

<img amplitude-song-info="cover_art_url" amplitude-main-song-info="true"/>

What this does is it will show the album art for whatever song is being played. There are two attributes. The first one amplitude-song-info="cover_art_url" defines the meta data we should use for the element. In this case, whatever is defined in our song object (discussed later) for cover_art_url will be set to the src attribute of the image.

The next attribute, amplitude-main-song-info="true" states that this will show the cover_art_url for whatever song is playing.

Our player element should now look like this:

...
  <div id="single-song-player">
    <img amplitude-song-info="cover_art_url" amplitude-main-song-info="true"/>
  </div>
...

Adding Song Progress

A unique element in AmplitudeJS is the song played progress bar. It visualizes how far along the song being played. In a later tutorial I will dive in on some of the specifics and how to style the element. For now, add the following HTML to your player right below the image:

<div class="bottom-container">
      <progress class="amplitude-song-played-progress" amplitude-main-song-played-progress="true" id="song-played-progress"></progress>
</div>

You will notice on the progress bar the class of amplitude-song-played-progress. This alerts AmplitudeJS that this progress element will display the current progress played in the song. We also have the attribute amplitude-main-song-played-progress="true". This means that whatever song being played this will show the progress for that song. It is the main area to find that information.

Adding Time Information

Below the progress bar, we will add a few time meta data fields. This will give a number read out of how long the song is and how far into the song we are. As discussed in https://serversideup.net/working-with-amplitudejs-song-object-metadata, there are lots of different time meta data fields. For this player, we are only going to use:

  • Current Minutes
  • Current Seconds
  • Duration Minutes
  • Duration Seconds

You can use whatever you want, I like scoping each into their own span just for full control, but you can use a time stamp or whatever you want. Add the following HTML below the progress bar:

<div class="time-container">
  <span class="current-time">
    <span class="amplitude-current-minutes" amplitude-main-current-minutes="true"></span>:<span class="amplitude-current-seconds" amplitude-main-current-seconds="true"></span>
  </span>
  <span class="duration">
    <span class="amplitude-duration-minutes" amplitude-main-duration-minutes="true"></span>:<span class="amplitude-duration-seconds" amplitude-main-duration-seconds="true"></span>
  </span>
</div>

The time container that wraps everything is not an AmplitudeJS specific element. It’s solely a structural element. As you notice, AmplitudeJS fits right in with structural elements and only binds the information needed to the elements specified.

In the code, there are the following classes:
* amplitude-current-minutes
* amplitude-current-seconds
* amplitude-duration-minutes
* amplitude-duration-seconds

Each of these elements has an attribute amplitude-main-[WHATEVER-ELEMENT] (ex. amplitude-main-current-seconds). This means that they will display the appropriate data for whatever song is playing since they are main elements. When we dive into playlists and multiple songs per page, we will notice that these are linked to a playlist or a song and will display data for the specific song or the specific playlist. For this example there is only one song, so it needs to be the main data.

As with everything we’ve added, you can apply any styles you want through CSS. The next section, we will add some control elements, these have a few styling guidelines.

Adding Play Pause Element

The Play/Pause button is probably the most important element in AmplitudeJS. It does exactly what it’s name states, it either plays or pauses the current song depending on the state of the song. It’s a toggle button so the individual element will act differently depending on the state of the player.

Add the following HTML below your time elements:

<div class="control-container">
  <div class="amplitude-play-pause" amplitude-main-play-pause="true" id="play-pause"></div>
</div>

The control container is just a structural element, and is not an Amplitude specific element. We want to focus on the element amplitude-play-pause. You can apply a class to ANY element you want and when the user touches or clicks the element, it will toggle play or pause. Before we get into the styling details, I’d like to point out, this is an element with the attribute amplitude-main-play-pause="true". This means it will play or pause on a global level. Whatever song is active whether it’s a playlist, individual song, or the only song will get toggled depending on the state of the player.

Now, when Amplitude initializes (see Initializing AmplitudeJS), there will be an additional class that gets added to this element called amplitude-paused. This is the current state of the player on initialization. When the button is clicked, the class will be removed and the class amplitude-playing will be added. These classes allow the developer to style the element based on the state of the player. AmplitudeJS will NEVER add HTML to the page. It will only adjust classes to represent the state of the player.

Now a common use case is to use an image to represent the play or pause state of the player. Do not put an image inside of the element!! Instead set it in the CSS as the background-image attribute like this:

div.amplitude-play-pause {
  width: 74px;
  height: 74px;
  cursor: pointer;
  float: left;
  margin-left: 10px;
}

div.amplitude-play-pause.amplitude-paused {
  background: url('../img/play.svg');
  background-size: cover;
}

div.amplitude-play-pause.amplitude-playing {
  background: url('../img/pause.svg');
  background-size: cover;
}

The reason we won’t put the image inside of the element is AmplitudeJS binds a click/touch handler to the element. Javascript might detect the click on the inner element and it won’t handle correctly. You can do whatever you want in the CSS and add the style accordingly.

Adding Now Playing Meta Data

Before we initialize AmplitudeJS, let’s add the last HTML we need to display the now playing meta data. Below the play/pause button add the following HTML;

<div class="meta-container">
  <span amplitude-song-info="name" amplitude-main-song-info="true" class="song-name"></span>
  <span amplitude-song-info="artist" amplitude-main-song-info="true"></span>
</div>

Once again, meta container is not an AmplitudeJS element, but the rest of them are. We are showing the song name and artist. As discussed in https://serversideup.net/working-with-amplitudejs-song-object-metadata, these elements get populated with the text from the song meta data. Whatever is in the amplitude-song-info attribute relating to the song object is inserted in the element. These are also main elements as noted by amplitude-main-song-info="true". This means whatever song is playing, the data gets added to the element. These can be scoped per song, per playlist, or global.

So now we have our HTML laid out for AmplitudeJS to bind to! All CSS can be found here: amplitudejs/examples/single-song at master · 521dimensions/amplitudejs · GitHub along with the code that we stepped through. Next up is initializing AmplitudeJS!

Initializing AmplitudeJS

Now that we have our HTML set up, it’s time to activate it! This is done with the Amplitude.init() method: Initializing AmplitudeJS. The Amplitude.init() method initializes AmplitudeJS with a variety of different configuration options, callbacks, songs, playlists, etc. The most important being the songs. Now you don’t HAVE to even add a song to AmplitudeJS on configuration, you can dynamically load them if needed. However, in this case, we we will be initializing with one song.

The Amplitude.init() method takes a JSON object as it’s only parameter in there, you can define everything you need. Let’s add the following code to the bottom of the index.html file:

<script>
  Amplitude.init({
    "songs": [
      {
        "name": "Risin' High (feat Raashan Ahmad)",
        "artist": "Ancient Astronauts",
        "album": "We Are to Answer",
        "url": "../songs/Ancient Astronauts - Risin' High (feat Raashan Ahmad).mp3",
        "cover_art_url": "../album-art/we-are-to-answer.jpg"
      }
    ]
  });
</script>

A few things to note. First, this method runs when it’s called. It does not wait for a ready function or anything else. That means it should be called at the end of your document or wrapped inside a document.ready() method! If you call this method before you have your HTML, it won’t bind to any elements and it won’t do anything! Now, you can call Amplitude.bindNewElements() if your display changes and you need to add more AmplitudeJS elements. We will discuss that in a later tutorial.

Next, the songs are in an array. This is important to note because a lot of AmplitudeJS functions reference a song index. The only song we have in the array right now has an index of 0. This is programming so the first object starts at 0 and goes up. When creating playlists, these indexes will be used to create the playlist.

You can see in the song object, there’s a lot of meta data. The only required piece is the url. This points to the song that will be played by AmplitudeJS.

That’s it! By calling init() AmplitudeJS has bound all of the click/touch handlers to the elements and has loaded a song. The code from GitHub includes a few other pieces of JS that we will dive more in depth on in later tutorials. You can do cool things like bind key events to control AmplitudeJS on the keyboard and other click handlers.

Let me know if you have any questions or want me to explain something differently in the comment section below!

Keep Reading
View the course View the Course AmplitudeJS: From the Ground Up
Up Next → Unique Elements in AmplitudeJS

Support future content

The Ultimate Guide to Building APIs and Single-Page Applications with Laravel + VueJS + Capacitor book cover.

Psst... any earnings that we make off of our book is being reinvested to bringing you more content. If you like what you read, consider getting our book or get sweet perks by becoming a sponsor.

Written By Dan

Dan Pastori avatar Dan Pastori

Builder, creator, and maker. Dan Pastori is a Laravel certified developer with over 10 years experience in full stack development. When you aren't finding Dan exploring new techniques in programming, catch him at the beach or hiking in the National Parks.

Stay Up To Date

Be the first to know about AmplitudeJS updates, when you sign up for our email list.