Skip to content

Instantly share code, notes, and snippets.

@Bjarkemonsted
Created November 16, 2015 17:11
Show Gist options
  • Save Bjarkemonsted/77c6a387913b8a8ae6c6 to your computer and use it in GitHub Desktop.
Save Bjarkemonsted/77c6a387913b8a8ae6c6 to your computer and use it in GitHub Desktop.
Material Design Audio Player
<div class='background' id='background'>&nbsp;</div>
<div id='player'>
<audio id='mytrack' src=''>&nbsp;</audio>
<div id='artwork'>&nbsp;</div>
<div id='tracks'>
<div trackartist='Tobu & Syndec' trackname='Dusk' trackartwork='01.jpg'></div>
<div trackartist='Disfigure' trackname='Blank' trackartwork='02.jpg'></div>
<div trackartist='Alan Walker' trackname='Fade' trackartwork='03.jpg'></div>
</div>
<div id='ui'>
<div id="time">
<span id='elapsedtime'>00:00</span>
<span id='totaltime'>00:00</span>
</div>
<div id='progressbar'>
<div><span id='pointer'>&nbsp;</span></div>
</div>
<div id='controls'>
<button id='prev' class='control'>&nbsp;</button>
<button id='play' class='control'>&nbsp;</button>
<button id='stop' class='control'>&nbsp;</button>
<button id='next' class='control'>&nbsp;</button>
</div>
</div> <!-- UI -->
</div> <!-- player -->
<div class='banner'><p>FREE jQuery Tabs Plugin?</p>
<a href='http://codepen.io/MichaelMammoliti/pen/LpGWoN' target='_blank'>CHECK MY PEN HERE!</a></div>

Material Design Audio Player

Hi, first pen for me ;)

Made only with Javascript. Not tested yet with IE. Comment if there are bugs or whatever ;)

#Update-1: (18-07-2015)

  • Improved UI theme;
  • Better SASS.

#Update-2: (26-08-2015)

  • Better Javascript.

#Coming Soon:

  • OOP structure;
  • jQuery plugin;
  • Import your favorite tracks;
  • Fullscreen Mode;
  • Make it responsive;
  • Volume controls;
  • Fade-in / fade-out effect with javascript;
  • Better playlist view.

Forked from Michael Mammoliti's Pen Material Design Audio Player.

A Pen by Bjarke Mønsted on CodePen.

License.

// - Controls
var play = document.querySelector("#play"),
prev = document.querySelector("#prev"),
next = document.querySelector("#next"),
stop = document.querySelector("#stop"),
// - Time
elapsedTime = document.querySelector("#elapsedtime"),
totalTime = document.querySelector("#totaltime"),
progressBar = document.querySelector("#progressbar"),
audioControls = document.querySelector("#controls"),
// - UI elements
audio = document.querySelector("#mytrack"),
tracks = document.querySelector("#tracks"),
artwork = document.querySelector("#artwork"),
background = document.querySelector("#background"),
// - Interval
timer,
// - Volume
volume = audio.volume = 0.4,
// - Theme
colorTheme = "green",
colorThemeDefault = "azure",
// - Project root
projectDir = "http://michaelmammoliti.com/_projects/audioJS/",
// - Project folders
tracksDir = projectDir + "songs/",
artworksFolder = projectDir + "artworks/",
iconsFolder = projectDir + "icons/" + colorTheme + "/",
// - Tracks
defaultTrack = 1,
currentTrack = defaultTrack,
playlist = [],
// - Audio
duration,
audioState = "pause",
// - Auto
autoPlay = true,
autoRepeat = true;
// - Audio Controls
function playAudio()
{
var src = tracksDir + addZero(defaultTrack, 2) + ".mp3",
icon = iconsFolder + "pause.png";
// Autoload track
if(audio.getAttribute("src") === ""){ audio.src = src; }
audio.play(); // Play
audioState = "play";
changeBackgroundImage(play, icon);
// Update the time
timer = setInterval( updateTime, 100 );
}
// - Control's functions
function pauseAudio()
{
var icon = projectDir + "icons/" + colorThemeDefault + "/play.png";
audio.pause();
audioState = "pause";
changeBackgroundImage(play, icon);
clearInterval(timer);
}
function stopAudio()
{
audio.currentTime = 0;
clearInterval(timer);
}
// - Update DOM elements
// Activate the track
function updateActiveTrack(num)
{
tracks.children[num-1].classList.add("active");
}
// Chamge audio tag song
function changeSong(num)
{
currentTrack = parseInt(num);
var artworkSrc,
src = tracksDir + addZero(currentTrack, 2) + ".mp3";
// Delete CSS classes to all tracks
for(var i = 0; i < playlist.length; i++) { tracks.children[i].removeAttribute("class"); }
artworkSrc = artworksFolder + addZero(currentTrack, 2) + ".jpg";
audio.src = src;
artwork.src = artworkSrc;
updateActiveTrack(currentTrack);
changeBackgroundImage(artwork, artworkSrc);
changeBackgroundImage(document.body, artworkSrc);
if(audioState === "play") { playAudio(); }
}
// - TIME
function getAudioSeconds(string)
{
var seconds = string % 60;
seconds = addZero( Math.floor(seconds), 2 );
if(seconds < 60) { return seconds; } else { return "00"; }
}
function getAudioMinutes(string)
{
var minutes = string / 60;
minutes = addZero( Math.floor(minutes), 2 );
if(minutes < 60) { return minutes; } else { return "00"; }
}
// - FIX ZERO - Nice functions i made, i think sharing will it helps
// Add howManyZero to from the begin
function addZero(word, howManyZero)
{
var word = String(word);
while(word.length < howManyZero) { word = "0" + word; }
return word;
}
// - Remove howManyZero from the begin
function removeZero(word, howManyZero)
{
var word = String(word),
i = 0;
while(i < howManyZero)
{
if(word[0] === "0") { word = word.substr(1, word.length); } else { break; }
i++;
}
return word;
}
// - Manage DOM Nodes
function insertDOMElement(parent, htmlString)
{
parent.insertAdjacentHTML("beforeend", htmlString);
}
function createTrackItem(trackNum, trackTitle, trackArtist, trackImage)
{
var div = "";
div += "<artwork style='background-image: url(\"" + trackImage + "\")'></artwork>";
div += "<span>" + trackNum + ". " + trackArtist + " - " + trackTitle + "</span>";
return div;
}
function populateTrack()
{
var children, trackName, trackArtist, trackartwork, obj;
for(var i = 0; i < tracks.children.length; i++)
{
children = tracks.children[i],
trackName = children.getAttribute("trackname"),
trackArtist = children.getAttribute("trackartist"),
trackartwork = children.getAttribute("trackartwork"),
obj = {
title: trackName,
artist: trackArtist,
artwork: trackartwork
};
playlist.push(obj);
insertDOMElement(
children,
createTrackItem(
addZero((i+1) ,2),
playlist[i].title,
playlist[i].artist,
artworksFolder + playlist[i].artwork
)
);
children.removeAttribute("trackname");
children.removeAttribute("trackartist");
children.removeAttribute("trackartwork");
children.setAttribute("tracknum", i+1);
}
}
// - DOM Animation / Styles / Updates
function changeBackgroundImage(element, image)
{
element.style.backgroundImage = "url('" + image + "')";
}
function updateProgressBarPosition()
{
var percentage = (audio.currentTime * 100 / duration) + "%",
children = progressBar.children[0];
children.style.width = percentage;
}
function updateTime()
{
var audioTime = getAudioMinutes(audio.currentTime) + ":" + getAudioSeconds(audio.currentTime);
updateProgressBarPosition();
elapsedTime.innerHTML = audioTime;
if(audio.ended)
{
if(currentTrack === (playlist.length))
{
currentTrack = defaultTrack;
changeSong(currentTrack);
}
else
{
currentTrack = currentTrack + 1;
changeSong(currentTrack);
}
if(autoRepeat) { playAudio(); }
}
}
// - POPULATE HTML
populateTrack();
// - EVENTS
window.onload = function() { changeSong(defaultTrack); };
audio.addEventListener(
'loadedmetadata',
function()
{
var time = getAudioMinutes(duration) + ":" + getAudioSeconds(duration);
duration = audio.duration;
totalTime.innerHTML = time;
}
);
play.addEventListener(
"click",
function()
{
if(audioState === "pause")
{
playAudio();
updateActiveTrack( currentTrack );
}
else if(audioState === "play") { pauseAudio(); }
}
);
stop.addEventListener(
"click",
function()
{
stopAudio();
pauseAudio();
updateTime();
}
);
prev.addEventListener(
"click",
function()
{
if(currentTrack > 1)
{
stopAudio();
changeSong(currentTrack - 1);
}
else if(currentTrack === 1)
{
stopAudio();
changeSong(currentTrack);
}
}
);
next.addEventListener(
"click",
function()
{
if(currentTrack < playlist.length)
{
stopAudio();
updateTime();
changeSong(currentTrack + 1);
console.log(currentTrack);
}
else
{
currentTrack = 1;
changeSong(currentTrack);
}
}
);
progressBar.addEventListener(
"click",
function(e)
{
var mouseX,
percentage,
newTime;
if(e.offsetX){ mouseX = e.offsetX; }
if(mouseX == undefined && e.layerX) { mouseX = e.layerX; }
percentage = mouseX / progressBar.offsetWidth;
newTime = audio.duration * percentage;
audio.currentTime = newTime;
updateProgressBarPosition();
}
);
// - Add events to all tracks
for(var i = 0; i < playlist.length; i++)
{
tracks.children[i].addEventListener(
"click",
function()
{
var btn = this,
trackNum = parseInt(btn.getAttribute("tracknum"));
if(btn.classList[0] !== "active")
{
tracks.children[1].removeAttribute("class");
btn.classList.add("active");
changeSong(trackNum);
}
}
);
}
// - Add events to all audioControls
for(var i = 0; i < audioControls.children.length; i++)
{
audioControls.children[i].addEventListener(
"mousedown",
function()
{
var btn = this,
icon = iconsFolder + btn.id + ".png";
changeBackgroundImage( btn, icon );
if(btn.classList[0] !== "shadow")
{
for(var x = 0; x < audioControls.children.length; x++)
{
audioControls.children[x].classList.remove("shadow");
}
}
}
);
audioControls.children[i].addEventListener(
"mouseup",
function()
{
var btn = this,
icon = projectDir + "icons/" + colorThemeDefault + "/" + btn.id + ".png";
changeBackgroundImage( btn, icon );
}
);
}
$color: #7BC3C0
$color-ui: #748899
$color-theme: $color + 80
$color-text: $color-theme
$theme: "azure"
$radius: 4px
$spacing: 12px
$progressbar-height: $spacing/2
$url: "http://michaelmammoliti.com/_projects/audioJS/"
=prefix($propertyName, $value)
-webkit-#{$propertyName}: #{$value}
-moz-#{$propertyName}: #{$value}
-ms-#{$propertyName}: #{$value}
-o-#{$propertyName}: #{$value}
=radius($rad: $radius)
+prefix(border-radius, $rad)
=absolute-width
position: absolute
height: 100%
width: 100%
top: 0
left: 0
=bg($size: "cover")
background-repeat: no-repeat
background-position: center center
background-size: #{$size}
background-color: transparent
=before
content: " "
display: block
=clearfix
display: table
overflow: hidden
&:before
+before
@import url(http://fonts.googleapis.com/css?family=Open+Sans:400,300,600)
*
color: $color-text
font-size: 12px
font-family: 'Open Sans', sans-serif
padding: 0
margin: 0
border: 0
outline: none
box-sizing: border-box
html, body
width: 100%
height: 100%
body
+bg
+prefix(transition, background 1s ease 0s)
#player
width: $spacing * 35
left: 50%
top: 50%
background: $color-ui
position: absolute
overflow: hidden
+prefix(transform, translate(-50%, -50%))
+radius
#ui
width: 100%
background: $color-ui
#controls
width: 100%
+clearfix
.control
width: 25%
height: $spacing*5
float: left
cursor: pointer
+bg(20px)
+prefix(transition, background .1s ease 0s)
&:active
background-color: $color-ui - 10
#next
background-image: url("#{$url}/icons/#{$theme}/next.png")
#prev
background-image: url("#{$url}/icons/#{$theme}/prev.png")
#play
background-image: url("#{$url}/icons/#{$theme}/play.png")
#stop
background-image: url("#{$url}/icons/#{$theme}/stop.png")
#progressbar
width: 100%
display: block
height: $progressbar-height
background: $color-ui - 10
overflow: hidden
cursor: pointer
>div
width: 0%
height: $progressbar-height
float: left
background: $color
+prefix(transition, width .1s ease 0s)
#pointer
width: $progressbar-height
height: $progressbar-height
float: right
background: $color-theme
margin-right: -$progressbar-height
#time
width: 100%
padding: $spacing*1.5 $spacing
+clearfix
span
color: $color
width: 50%
float: left
&:first-of-type
text-align: left
&:last-of-type
text-align: right
#tracks
width: 100%
display: block
background: $color-ui - 10
+clearfix
div
width: 100%
cursor: pointer
padding: $spacing
+prefix(transition, all .5s ease 0s)
&:hover
*
color: $color
&.active
background: $color
+prefix(transition, all .5s ease 0s)
&:hover,
*
color: #fff
span
margin-right: $spacing
padding: 0 $spacing
height: $spacing*3
line-height: $spacing*3
color: $color-text
artwork
float: left
height: $spacing*3
width: $spacing*3
+radius
+bg
#artwork
width: 100%
height: 0
padding-bottom: 60%
background-image: url("../artworks/01.jpg")
background-position: center center
position: relative
+bg
+prefix(transition, background 1s ease 0s)
.background
+absolute-width
background: $color + 90
opacity: .7
.banner
display: table
overflow: hidden
position: absolute
right: 0
top: 50%
z-index: 11
+prefix(border-top-left-radius, 4px)
+prefix(border-bottom-left-radius, 4px)
+prefix(transform, translate(0, -50%))
P, a
padding: $spacing*1.6 $spacing*2
font-size: 1.5em
text-align: center
display: block
p
background-color: #fff
color: #888
a
color: #fff
background: $color
text-decoration: none
&:hover
background: $color - 20
@media screen and (max-height: 400px)
body
zoom: .4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment