Skip to content

Instantly share code, notes, and snippets.

@aldoyh
Last active May 13, 2024 14:29
Show Gist options
  • Save aldoyh/d9999934021c724b220232c4acd05efa to your computer and use it in GitHub Desktop.
Save aldoyh/d9999934021c724b220232c4acd05efa to your computer and use it in GitHub Desktop.
MP3 Player w/ GSAP ☘️
<div class='player-wrapper'>
<div class='player-title'>Now Playing</div>
<div class='player-song'>Shop Talk Show</div>
<div class='player-singer'>Chris Coyier & Dave Rupert</div>
<div class='progress-control'>
<progress class='player-progress' value='0'></progress>
<div class='progress-handler'></div>
</div>
<div class='player-control'>
<button class='player-play'><i class="fa fa-play-circle-o fa-4x"></i></button>
<button class='player-shuffle bottom '><i class="fa fa-random fa-2x"></i></button>
<button class='player-repeat top'><i class="fa fa-refresh fa-2x"></i></button>
<button class='player-prev left'><i class="fa fa-fast-backward fa-2x"></i></button>
<button class='player-next right'><i class="fa fa-fast-forward fa-2x"></i></button>
</div>
</div>
var player = document.querySelector('.player-wrapper'),
playerSong = player.querySelector('.player-song'),
playerSinger = player.querySelector('.player-singer'),
curSong = 0,
progress = player.querySelector('.player-progress'),
handler = player.querySelector('.progress-handler'),
play = player.querySelector('.player-play'),
prev = player.querySelector('.player-prev'),
next = player.querySelector('.player-next'),
repeat = player.querySelector('.player-repeat'),
shuffle = player.querySelector('.player-shuffle');
var audio = new Audio(),
songs = [{src: 'https://s3.amazonaws.com/ShopTalk/080_rapidfire_19.mp3',
singer: 'Chris Coyier & Dave Rupert',
name: 'Shop Talk Show'},
{src: 'https://ia600409.us.archive.org/9/items/MoonlightSonata_755/Beethoven-MoonlightSonata.mp3',
singer: 'Beethoven',
name: 'Moonlight Sonata'},
{src: 'http://public.npr.org/anon.npr-podcasts/podcast/510289/292601835/npr_292601835.mp3',
singer: 'NPR',
name: 'Planet Money Podcast'},
{src: 'http://public.npr.org/anon.npr-podcasts/podcast/510298/292175079/npr_292175079.mp3',
singer: 'NPR',
name: 'TED Radio Hour Podcast'}];
audio.addEventListener('loadedmetadata', function(){
progress.setAttribute('max', Math.floor(this.duration));
});
audio.addEventListener('timeupdate', function(){
progress.setAttribute('value', this.currentTime);
handler.style.left = this.currentTime/this.duration*100+'%';
});
audio.addEventListener('ended', function(){
playNext();
});
progress.addEventListener('click', function(e){
audio.currentTime = Math.floor(audio.duration) * (e.offsetX / e.target.offsetWidth);
handler.style.left = audio.currentTime/audio.duration*100+'%';
}, false);
handler.addEventListener('mousedown', function(e){
handler.style.left = e.offsetX;
},false);
play.addEventListener('click', function(){
if(audio.paused){
playSong(curSong);
}else{
audio.pause();
play.classList.remove('clicked');
}
},false);
next.addEventListener('mousedown', function(e){
this.classList.add('clicked');
playNext();
}, false);
next.addEventListener('mouseup', function(e){
this.classList.remove('clicked');
}, false);
prev.addEventListener('mousedown', function(e){
this.classList.add('clicked');
playPrev();
}, false);
prev.addEventListener('mouseup', function(e){
this.classList.remove('clicked');
}, false);
repeat.addEventListener('click', function(){
toggleClick(repeat, shuffle);
}, false);
shuffle.addEventListener('click', function(){
toggleClick(shuffle, repeat);
}, false);
function playNext(){
if(shuffle.classList.contains('clicked')){
//if play randomly
curSong = Math.floot(Math.Random()*songs.length);
} else if(!repeat.classList.contains('clicked')){
//if play regularly
curSong = curSong==songs.length-1 ? 0 : curSong+1;
}
//if play recursively, do nothing
playSong(curSong);
}
function playPrev(){
curSong = curSong? curSong-1:songs.length-1;
playSong(curSong);
}
function playSong(idx){
//change title
playerSong.textContext = songs[idx].song;
playerSinger.textContext = songs[idx].singer;
play.classList.add('clicked');
//audio.pause();
audio.src = songs[idx].src;
audio.load();
audio.play();
}
function toggleClick(self, other){
if(self.classList.contains('clicked')){
self.classList.remove('clicked');
} else {
self.classList.add('clicked');
other.classList.remove('clicked');
}
}
@import url("https://fonts.googleapis.com/css?family=Open+Sans:400,600");
//variables about length
$font-size: 28px;
$l-control: 450px;
$l-play: 250px;
$l-play-margin: ($l-control - $l-play) / 2;
$l-button-margin: ($l-play-margin - $font-size)/ 2;
//variables about colors
$c-grey-dark: #222428;
$c-grey: #292F33;
$c-grey-light: #2D343A;
$c-pink: #FF665E;
$c-crimson: #E62D31;
*, :after, :before{
margin: 0;
padding: 0;
border: none;
}
@mixin grey-button($radius, $shadow-width: 4px, $blur:5px){
width: $radius;
height: $radius;
border-radius: 50%;
background: $c-grey;
box-shadow: inset 0 3px $c-grey-light,
0px -1px 3px $c-grey-dark,
0px $shadow-width $blur $c-grey-dark;
}
@mixin neon-effect(){
background: -webkit-linear-gradient(top, $c-crimson, $c-pink , $c-crimson);
background: -moz-linear-gradient(top, $c-crimson, $c-pink , $c-crimson);
background: linear-gradient(top, $c-crimson, $c-pink, $c-crimson);
box-shadow: 0 0 10px $c-crimson;
}
@mixin progress-bar(){
background: #252B30;
box-shadow:
0 2px 2px $c-grey-light,
inset 0 2px $c-grey-dark;
}
body{
background: #333;
font-size: $font-size;
font-family:'Open Sans', sans-serif;
}
.player-wrapper{
background: $c-grey;
width: 640px;
height: 1136px;
text-align: center;
margin: 10px auto;
overflow: hidden;
box-shadow: 0 0 20px rgba(0,0,0,0.8);
}
.player-title{
color: $c-pink;
text-transform: uppercase;
font-weight: bold;
text-shadow: inset 0 0 1px $c-crimson;
margin: 120px auto 50px;
}
.player-song{
color:#96999D;
font-size: 1.5 * $font-size;
}
.player-singer{
color: #636867;
font-size: 1.3 * $font-size;
margin-top: $font-size;
}
.player-singer, .player-song{
text-shadow: 1px 2px $c-grey-dark;
}
.progress-control{
margin: 120px auto 100px;
position: relative;
}
progress.player-progress{
width: 100%;
height: 10px;
@include progress-bar();
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
progress[value]::-moz-progress-bar {
@include progress-bar();
}
progress[value]::-webkit-progress-bar {
@include progress-bar();
}
progress[value]::-webkit-progress-value {
@include neon-effect();
}
.progress-handler{
@include grey-button(30px);
top: 12.5px;
position: absolute;
z-index: 2;
}
.player-control{
margin: 0 auto;
@include grey-button($l-control, $blur:10px);
position: relative;
button{
background: transparent;
color: #222729;
display: block;
text-shadow: 1px 2px $c-grey-light;
position: absolute;
cursor: pointer;
&:active, &:focus{
outline: none;
}
}
.clicked{
color: $c-crimson;
}
.top, .bottom{
left: ($l-control - 28px)/ 2; // 50%;
}
.left, .right{
top: ($l-control - 28px)/ 2;
}
.top{
top: $l-button-margin;
}
.bottom{
bottom: $l-button-margin;
}
.left{
left: $l-button-margin;
}
.right{
right: $l-button-margin;
}
.player-play{
@include grey-button($l-play, 10px, 20px);
position: absolute;
top: $l-play-margin;
left: $l-play-margin;
background: -webkit-linear-gradient(top, $c-grey-dark, $c-grey-light);
}
}
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment