Simple Beautiful Fully Functional Music | Audio Player.
Design inspired by: https://dribbble.com/shots/4240318-Made-with-InVision-Studio-Music-Player
A Pen by Himalaya Singh on CodePen.
<div id="player-bg-artwork"></div> | |
<div id="player-bg-layer"></div> | |
<div id="player-container"> | |
<div id="player"> | |
<div id="player-track"> | |
<div id="album-name"></div> | |
<div id="track-name"></div> | |
<div id="track-time"> | |
<div id="current-time"></div> | |
<div id="track-length"></div> | |
</div> | |
<div id="seek-bar-container"> | |
<div id="seek-time"></div> | |
<div id="s-hover"></div> | |
<div id="seek-bar"></div> | |
</div> | |
</div> | |
<div id="player-content"> | |
<div id="album-art"> | |
<img src="https://singhimalaya.github.io/Codepen/assets/img/album-arts/1.jpg" class="active" id="_1" /> | |
<img src="https://singhimalaya.github.io/Codepen/assets/img/album-arts/2.jpg" id="_2" /> | |
<img src="https://singhimalaya.github.io/Codepen/assets/img/album-arts/3.jpg" id="_3" /> | |
<img src="https://singhimalaya.github.io/Codepen/assets/img/album-arts/4.jpg" id="_4" /> | |
<img src="https://singhimalaya.github.io/Codepen/assets/img/album-arts/5.jpg" id="_5" /> | |
<div id="buffer-box">Buffering ...</div> | |
</div> | |
<div id="player-controls"> | |
<div class="control"> | |
<div class="button" id="play-previous"> | |
<i class="fas fa-backward"></i> | |
</div> | |
</div> | |
<div class="control"> | |
<div class="button" id="play-pause-button"> | |
<i class="fas fa-play"></i> | |
</div> | |
</div> | |
<div class="control"> | |
<div class="button" id="play-next"> | |
<i class="fas fa-forward"></i> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> |
Simple Beautiful Fully Functional Music | Audio Player.
Design inspired by: https://dribbble.com/shots/4240318-Made-with-InVision-Studio-Music-Player
A Pen by Himalaya Singh on CodePen.
$(function () { | |
const playerTrack = $("#player-track"); | |
const bgArtwork = $("#player-bg-artwork"); | |
const albumName = $("#album-name"); | |
const trackName = $("#track-name"); | |
const albumArt = $("#album-art"); | |
const sArea = $("#seek-bar-container"); | |
const seekBar = $("#seek-bar"); | |
const trackTime = $("#track-time"); | |
const seekTime = $("#seek-time"); | |
const sHover = $("#s-hover"); | |
const playPauseButton = $("#play-pause-button"); | |
const tProgress = $("#current-time"); | |
const tTime = $("#track-length"); | |
const playPreviousTrackButton = $("#play-previous"); | |
const playNextTrackButton = $("#play-next"); | |
const albums = [ | |
"Me & You", | |
"Dawn", | |
"Electro Boy", | |
"Home", | |
"Proxy (Original Mix)" | |
]; | |
const trackNames = [ | |
"Alex Skrindo - Me & You", | |
"Skylike - Dawn", | |
"Kaaze - Electro Boy", | |
"Jordan Schor - Home", | |
"Martin Garrix - Proxy" | |
]; | |
const albumArtworks = ["_1", "_2", "_3", "_4", "_5"]; | |
const trackUrl = [ | |
"https://singhimalaya.github.io/Codepen/assets/music/1.mp3", | |
"https://singhimalaya.github.io/Codepen/assets/music/2.mp3", | |
"https://singhimalaya.github.io/Codepen/assets/music/3.mp3", | |
"https://singhimalaya.github.io/Codepen/assets/music/4.mp3", | |
"https://singhimalaya.github.io/Codepen/assets/music/5.mp3" | |
]; | |
let bgArtworkUrl, | |
i = playPauseButton.find("i"), | |
seekT, | |
seekLoc, | |
seekBarPos, | |
cM, | |
ctMinutes, | |
ctSeconds, | |
curMinutes, | |
curSeconds, | |
durMinutes, | |
durSeconds, | |
playProgress, | |
bTime, | |
nTime = 0, | |
buffInterval = null, | |
tFlag = false, | |
currIndex = -1; | |
function playPause() { | |
setTimeout(function () { | |
if (audio.paused) { | |
playerTrack.addClass("active"); | |
albumArt.addClass("active"); | |
checkBuffering(); | |
i.attr("class", "fas fa-pause"); | |
audio.play(); | |
} else { | |
playerTrack.removeClass("active"); | |
albumArt.removeClass("active"); | |
clearInterval(buffInterval); | |
albumArt.removeClass("buffering"); | |
i.attr("class", "fas fa-play"); | |
audio.pause(); | |
} | |
}, 300); | |
} | |
function showHover(event) { | |
seekBarPos = sArea.offset(); | |
seekT = event.clientX - seekBarPos.left; | |
seekLoc = audio.duration * (seekT / sArea.outerWidth()); | |
sHover.width(seekT); | |
cM = seekLoc / 60; | |
ctMinutes = Math.floor(cM); | |
ctSeconds = Math.floor(seekLoc - ctMinutes * 60); | |
if (ctMinutes < 0 || ctSeconds < 0) return; | |
if (ctMinutes < 0 || ctSeconds < 0) return; | |
if (ctMinutes < 10) ctMinutes = "0" + ctMinutes; | |
if (ctSeconds < 10) ctSeconds = "0" + ctSeconds; | |
if (isNaN(ctMinutes) || isNaN(ctSeconds)) seekTime.text("--:--"); | |
else seekTime.text(ctMinutes + ":" + ctSeconds); | |
seekTime.css({ left: seekT, "margin-left": "-21px" }).fadeIn(0); | |
} | |
function hideHover() { | |
sHover.width(0); | |
seekTime | |
.text("00:00") | |
.css({ left: "0px", "margin-left": "0px" }) | |
.fadeOut(0); | |
} | |
function playFromClickedPos() { | |
audio.currentTime = seekLoc; | |
seekBar.width(seekT); | |
hideHover(); | |
} | |
function updateCurrTime() { | |
nTime = new Date(); | |
nTime = nTime.getTime(); | |
if (!tFlag) { | |
tFlag = true; | |
trackTime.addClass("active"); | |
} | |
curMinutes = Math.floor(audio.currentTime / 60); | |
curSeconds = Math.floor(audio.currentTime - curMinutes * 60); | |
durMinutes = Math.floor(audio.duration / 60); | |
durSeconds = Math.floor(audio.duration - durMinutes * 60); | |
playProgress = (audio.currentTime / audio.duration) * 100; | |
if (curMinutes < 10) curMinutes = "0" + curMinutes; | |
if (curSeconds < 10) curSeconds = "0" + curSeconds; | |
if (durMinutes < 10) durMinutes = "0" + durMinutes; | |
if (durSeconds < 10) durSeconds = "0" + durSeconds; | |
if (isNaN(curMinutes) || isNaN(curSeconds)) tProgress.text("00:00"); | |
else tProgress.text(curMinutes + ":" + curSeconds); | |
if (isNaN(durMinutes) || isNaN(durSeconds)) tTime.text("00:00"); | |
else tTime.text(durMinutes + ":" + durSeconds); | |
if ( | |
isNaN(curMinutes) || | |
isNaN(curSeconds) || | |
isNaN(durMinutes) || | |
isNaN(durSeconds) | |
) | |
trackTime.removeClass("active"); | |
else trackTime.addClass("active"); | |
seekBar.width(playProgress + "%"); | |
if (playProgress == 100) { | |
i.attr("class", "fa fa-play"); | |
seekBar.width(0); | |
tProgress.text("00:00"); | |
albumArt.removeClass("buffering").removeClass("active"); | |
clearInterval(buffInterval); | |
} | |
} | |
function checkBuffering() { | |
clearInterval(buffInterval); | |
buffInterval = setInterval(function () { | |
if (nTime == 0 || bTime - nTime > 1000) albumArt.addClass("buffering"); | |
else albumArt.removeClass("buffering"); | |
bTime = new Date(); | |
bTime = bTime.getTime(); | |
}, 100); | |
} | |
function selectTrack(flag) { | |
if (flag == 0 || flag == 1) ++currIndex; | |
else --currIndex; | |
if (currIndex > -1 && currIndex < albumArtworks.length) { | |
if (flag == 0) i.attr("class", "fa fa-play"); | |
else { | |
albumArt.removeClass("buffering"); | |
i.attr("class", "fa fa-pause"); | |
} | |
seekBar.width(0); | |
trackTime.removeClass("active"); | |
tProgress.text("00:00"); | |
tTime.text("00:00"); | |
currAlbum = albums[currIndex]; | |
currTrackName = trackNames[currIndex]; | |
currArtwork = albumArtworks[currIndex]; | |
audio.src = trackUrl[currIndex]; | |
nTime = 0; | |
bTime = new Date(); | |
bTime = bTime.getTime(); | |
if (flag != 0) { | |
audio.play(); | |
playerTrack.addClass("active"); | |
albumArt.addClass("active"); | |
clearInterval(buffInterval); | |
checkBuffering(); | |
} | |
albumName.text(currAlbum); | |
trackName.text(currTrackName); | |
albumArt.find("img.active").removeClass("active"); | |
$("#" + currArtwork).addClass("active"); | |
bgArtworkUrl = $("#" + currArtwork).attr("src"); | |
bgArtwork.css({ "background-image": "url(" + bgArtworkUrl + ")" }); | |
} else { | |
if (flag == 0 || flag == 1) --currIndex; | |
else ++currIndex; | |
} | |
} | |
function initPlayer() { | |
audio = new Audio(); | |
selectTrack(0); | |
audio.loop = false; | |
playPauseButton.on("click", playPause); | |
sArea.mousemove(function (event) { | |
showHover(event); | |
}); | |
sArea.mouseout(hideHover); | |
sArea.on("click", playFromClickedPos); | |
$(audio).on("timeupdate", updateCurrTime); | |
playPreviousTrackButton.on("click", function () { | |
selectTrack(-1); | |
}); | |
playNextTrackButton.on("click", function () { | |
selectTrack(1); | |
}); | |
} | |
initPlayer(); | |
}); |
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> |
* { | |
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, | |
Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; | |
user-select: none; | |
-webkit-tap-highlight-color: transparent; | |
} | |
body { | |
margin: 0; | |
background-color: #f1f9f9; | |
} | |
*:focus { | |
outline: none; | |
} | |
body { | |
margin: 0; | |
background-color: #ffeff5; | |
} | |
#player-container { | |
position: absolute; | |
top: 50%; | |
right: 0; | |
left: 0; | |
width: 430px; | |
height: 100px; | |
margin: -4px auto; | |
} | |
#player-bg-artwork { | |
position: fixed; | |
top: -30px; | |
right: -30px; | |
bottom: -30px; | |
left: -30px; | |
background-image: url("https://raw.githubusercontent.com/himalayasingh/music-player-1/master/img/_1.jpg"); | |
background-repeat: no-repeat; | |
background-size: cover; | |
background-position: 50%; | |
filter: blur(40px); | |
-webkit-filter: blur(40px); | |
z-index: 1; | |
} | |
#player-bg-layer { | |
position: fixed; | |
top: 0; | |
right: 0; | |
bottom: 0; | |
left: 0; | |
background-color: #fff; | |
opacity: 0.5; | |
z-index: 2; | |
} | |
#player { | |
position: relative; | |
height: 100%; | |
z-index: 3; | |
} | |
#player-track { | |
position: absolute; | |
top: 0; | |
right: 15px; | |
left: 15px; | |
padding: 13px 22px 10px 184px; | |
background-color: #fff7f7; | |
border-radius: 15px 15px 0 0; | |
transition: 0.3s ease top; | |
z-index: 1; | |
} | |
#player-track.active { | |
top: -92px; | |
} | |
#album-name { | |
color: #54576f; | |
font-size: 17px; | |
font-weight: bold; | |
} | |
#track-name { | |
color: #acaebd; | |
font-size: 13px; | |
margin: 2px 0 13px 0; | |
} | |
#track-time { | |
height: 12px; | |
margin-bottom: 3px; | |
overflow: hidden; | |
} | |
#current-time { | |
float: left; | |
} | |
#track-length { | |
float: right; | |
} | |
#current-time, | |
#track-length { | |
color: transparent; | |
font-size: 11px; | |
background-color: #ffe8ee; | |
border-radius: 10px; | |
transition: 0.3s ease all; | |
} | |
#track-time.active #current-time, | |
#track-time.active #track-length { | |
color: #f86d92; | |
background-color: transparent; | |
} | |
#seek-bar-container, | |
#seek-bar { | |
position: relative; | |
height: 4px; | |
border-radius: 4px; | |
} | |
#seek-bar-container { | |
background-color: #ffe8ee; | |
cursor: pointer; | |
} | |
#seek-time { | |
position: absolute; | |
top: -29px; | |
color: #fff; | |
font-size: 12px; | |
white-space: pre; | |
padding: 5px 6px; | |
border-radius: 4px; | |
display: none; | |
} | |
#s-hover { | |
position: absolute; | |
top: 0; | |
bottom: 0; | |
left: 0; | |
opacity: 0.2; | |
z-index: 2; | |
} | |
#seek-time, | |
#s-hover { | |
background-color: #3b3d50; | |
} | |
#seek-bar { | |
content: ""; | |
position: absolute; | |
top: 0; | |
bottom: 0; | |
left: 0; | |
width: 0; | |
background-color: #fd6d94; | |
transition: 0.2s ease width; | |
z-index: 1; | |
} | |
#player-content { | |
position: relative; | |
height: 100%; | |
background-color: #fff; | |
box-shadow: 0 30px 80px #656565; | |
border-radius: 15px; | |
z-index: 2; | |
} | |
#album-art { | |
position: absolute; | |
top: -40px; | |
width: 115px; | |
height: 115px; | |
margin-left: 40px; | |
transform: rotateZ(0); | |
transition: 0.3s ease all; | |
box-shadow: 0 0 0 10px #fff; | |
border-radius: 50%; | |
overflow: hidden; | |
} | |
#album-art.active { | |
top: -60px; | |
box-shadow: 0 0 0 4px #fff7f7, 0 30px 50px -15px #afb7c1; | |
} | |
#album-art:before { | |
content: ""; | |
position: absolute; | |
top: 50%; | |
right: 0; | |
left: 0; | |
width: 20px; | |
height: 20px; | |
margin: -10px auto 0 auto; | |
background-color: #d6dee7; | |
border-radius: 50%; | |
box-shadow: inset 0 0 0 2px #fff; | |
z-index: 2; | |
} | |
#album-art img { | |
display: block; | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
opacity: 0; | |
z-index: -1; | |
} | |
#album-art img.active { | |
opacity: 1; | |
z-index: 1; | |
} | |
#album-art.active img.active { | |
z-index: 1; | |
animation: rotateAlbumArt 3s linear 0s infinite forwards; | |
} | |
@keyframes rotateAlbumArt { | |
0% { | |
transform: rotateZ(0); | |
} | |
100% { | |
transform: rotateZ(360deg); | |
} | |
} | |
#buffer-box { | |
position: absolute; | |
top: 50%; | |
right: 0; | |
left: 0; | |
height: 13px; | |
color: #1f1f1f; | |
font-size: 13px; | |
font-family: Helvetica; | |
text-align: center; | |
font-weight: bold; | |
line-height: 1; | |
padding: 6px; | |
margin: -12px auto 0 auto; | |
background-color: rgba(255, 255, 255, 0.19); | |
opacity: 0; | |
z-index: 2; | |
} | |
#album-art img, | |
#buffer-box { | |
transition: 0.1s linear all; | |
} | |
#album-art.buffering img { | |
opacity: 0.25; | |
} | |
#album-art.buffering img.active { | |
opacity: 0.8; | |
filter: blur(2px); | |
-webkit-filter: blur(2px); | |
} | |
#album-art.buffering #buffer-box { | |
opacity: 1; | |
} | |
#player-controls { | |
width: 250px; | |
height: 100%; | |
margin: 0 5px 0 141px; | |
float: right; | |
overflow: hidden; | |
} | |
.control { | |
width: 33.333%; | |
float: left; | |
padding: 12px 0; | |
} | |
.button { | |
width: 26px; | |
height: 26px; | |
padding: 25px; | |
background-color: #fff; | |
border-radius: 6px; | |
cursor: pointer; | |
} | |
.button i { | |
display: block; | |
color: #d6dee7; | |
font-size: 26px; | |
text-align: center; | |
line-height: 1; | |
} | |
.button, | |
.button i { | |
transition: 0.2s ease all; | |
} | |
.button:hover { | |
background-color: #d6d6de; | |
} | |
.button:hover i { | |
color: #fff; | |
} |
<link href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" rel="stylesheet" /> |