<html lang="en">
<head>
<title>Simple Music Player</title>
<!-- Load FontAwesome icons -->
<link rel="stylesheet"
href=
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css">
<!-- Load the custom CSS style file -->
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div id="cont"><div class="player">
<!-- Define the section for displaying details -->
<div class="details">
<div class="wah">
<div class="track-art"></div>
<div class="middle">
<div class="text">caiyini!!</div>
</div>
</div>
<div class="now-playing">PLAYING x OF y</div>
<div class="track-name">Track Name</div>
<div class="track-artist">Track Artist</div>
</div>
<!-- Define the section for displaying track buttons -->
<div class="buttons">
<div class="prev-track" onclick="prevTrack()">
<i class="fa fa-step-backward fa-2x"></i>
</div>
<div class="playpause-track" onclick="playpauseTrack()">
<i class="fa fa-play-circle fa-5x"></i>
</div>
<div class="next-track" onclick="nextTrack()">
<i class="fa fa-step-forward fa-2x"></i>
</div>
</div>
<!-- Define the section for displaying the seek slider-->
<div class="slider_container">
<div class="current-time">00:00</div>
<input type="range" min="1" max="100"
value="0" class="seek_slider" onchange="seekTo()">
<div class="total-duration">00:00</div>
</div>
<!-- Define the section for displaying the volume slider-->
<div class="slider_container">
<i class="fa fa-volume-down"></i>
<input type="range" min="1" max="100"
value="99" class="volume_slider" onchange="setVolume()">
<i class="fa fa-volume-up"></i>
</div>
</div></div>
<!-- Load the main script for the player -->
<script src="main.js"></script>
</body>
</html>
<style>
::selection { /* Code for Firefox */
color: #FF86BC;
background: transparent;
}
::selection {
color: #FF86BC;
background: transparent;
}
@font-face {
font-family: space ranger;
src:url(https://dl.dropbox.com/s/eis23duz97yq7e1/spacerangerlaserital.ttf);
}
@font-face {
font-family:sweetheart;
src:url(https://dl.dropbox.com/s/qsbxaucivq93z8r/sweet_heart.ttf);
}
#cont {
display:block;
margin-left:auto;
margin-right:auto;
width:25em;
height:34em;
border:1px solid black;
background: rgb(255,255,255);
background: linear-gradient(0deg, rgba(255,255,255,1) 0%, rgba(255,243,249,1) 39%, rgba(255,185,222,1) 100%);
border-radius:5%;
}
/* Using flex with the column direction to
align items in a vertical direction */
.player {
height: 20em;
font-family: space ranger;
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
}
.details {
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
margin-top:25px;
/* color */
color:white;
text-shadow:1px 0px black, -1px 0px black, 0px 1px black, 0px -1px black;
}
.middle {
transition: .5s ease;
opacity: 0;
position: relative;
top:-28%;
text-align: center;
}
.wah:hover .track-art {
opacity: 0.7;
filter:blur(2px);
}
.wah:hover .middle {
opacity: 1;
}
.text {
color: white;
font-size: 1.7em;
text-shadow: -1px 0 #000, 0 1px #000, 1px 0 #000, 0 -1px #000, 0 0;
font-family:space ranger;
}
.track-art {
opacity: 1;
display: block;
height: auto;
transition: .5s ease;
backface-visibility: hidden;
}
.track-art {
margin: .3em;
margin-top:13em;
height: 14em;
width: 17em;
background-image: URL(
"https://source.unsplash.com/Qrspubmx6kE/640x360") !important;
background-size: cover;
background-position: center;
border-radius: 4%;
border:1px solid black;
}
.buttons {
transition:all .5s ease;
}
/* Changing the font sizes to suitable ones */
.now-playing {
font-size: 1rem;
}
@font-face {
font-family:aeroblade;
src:url(https://dl.dropbox.com/s/rp1c9fy6nef7l15/Aeroblade%20DEMO.ttf);
}
.track-name {
font-size: 1.3rem;
font-family:aeroblade;
margin-top:.3em;
margin-bottom:.3em;
}
.track-artist {
font-size: 1.2rem;
}
/* Using flex with the row direction to
align items in a horizontal direction */
.buttons {
display: flex;
flex-direction: row;
align-items: center;
}
.playpause-track,
.prev-track,
.next-track {
padding: 25px;
opacity: 0.8;
color:#FF80BA;
/* Smoothly transition the opacity */
transition: opacity .2s;
}
/* Change the opacity when mouse is hovered */
.playpause-track:hover,
.prev-track:hover,
.next-track:hover {
opacity: 1.0;
}
/* Define the slider width so that it scales properly */
.slider_container {
width: 75%;
max-width: 400px;
display: flex;
justify-content: center;
align-items: center;
}
/* Modify the appearance of the slider */
.seek_slider, .volume_slider {
appearance: none;
appearance: none;
appearance: none;
height: 5px;
background: #FF80BA;
opacity: 0.7;
transition: .2s;
transition: opacity .2s;
}
/* Modify the appearance of the slider thumb */
.seek_slider::slider-thumb {
appearance: none;
appearance: none;
appearance: none;
width: 20px;
height: 20px;
background: transparent;
cursor: pointer;
background-image: url("https://xyz.crd.co/assets/images/gallery21/02e87878.gif?v=da780c6a")
}
.volume_slider::slider-thumb {
appearance: none;
appearance: none;
appearance: none;
width: 20px;
height: 20px;
background: transparent;
cursor: pointer;
background-image: url("https://xyz.crd.co/assets/images/gallery21/6e61105b.gif?v=da780c6a")
}
/* Change the opacity when mouse is hovered */
.seek_slider:hover,
.volume_slider:hover {
opacity: 1.0;
}
.seek_slider {
width: 60%;
}
.volume_slider {
width: 30%;
}
.current-time,
.total-duration {
padding: 10px;
font-family:sweetheart;
}
i.fa-volume-down,
i.fa-volume-up {
padding: 10px;
color:white;
text-shadow:1px 0px #FF5AA4, -1px 0px #FF5AA4, 0px -1px #FF5AA4, 0px 1px #FF5AA4;
transition:all .4s ease;
}
i.fa-volume-down:hover,
i.fa-volume-up:hover {
padding: 10px;
color:#FF5AA4;
text-shadow:none;
transition:all .4s ease;
}
/* Change the mouse cursor to a pointer
when hovered over */
i.fa-play-circle,
i.fa-pause-circle,
i.fa-step-forward,
i.fa-step-backward {
cursor: pointer;
}
</style>
<script>
let now_playing = document.querySelector(".now-playing");
let track_art = document.querySelector(".track-art");
let track_name = document.querySelector(".track-name");
let track_artist = document.querySelector(".track-artist");
let playpause_btn = document.querySelector(".playpause-track");
let next_btn = document.querySelector(".next-track");
let prev_btn = document.querySelector(".prev-track");
let seek_slider = document.querySelector(".seek_slider");
let volume_slider = document.querySelector(".volume_slider");
let curr_time = document.querySelector(".current-time");
let total_duration = document.querySelector(".total-duration");
// Specify globally used values
let track_index = 0;
let isPlaying = false;
let updateTimer;
// Create the audio element for the player
let curr_track = document.createElement('audio');
// Define the list of tracks that have to be played
let track_list = [
{
name: "ready to love",
artist: "seventeen",
image: "https://cdn.discordapp.com/attachments/822735059428704266/897276537710202910/HELLO_JUNHUI.jpeg",
path: "https://cdn.discordapp.com/attachments/794206362262437910/892802405832470619/SEVENTEEN__Ready_to_love_Official_MV.mp3"
},
{
name: "weekend",
artist: "taeyeon",
image: "https://cdn.discordapp.com/attachments/822735059428704266/897276547591962634/weekend_3.jpeg",
path: "https://cdn.discordapp.com/attachments/794206362262437910/882499119606800414/weekend_taeyeon.mp3"
},
{
name: "fairy of shampoo",
artist: "tomorrow x together",
image: "https://cdn.discordapp.com/attachments/822735059428704266/897276525731262464/txt_class_3.jpeg",
path: "https://cdn.discordapp.com/attachments/794206362262437910/897275806336815114/TXT_Fairy_of_Shampoo_Lyrics___Color_Coded_Lyrics_Han_Rom_Eng.mp3",
},
];
//
//
function loadTrack(track_index) {
// Clear the previous seek timer
clearInterval(updateTimer);
resetValues();
// Load a new track
curr_track.src = track_list[track_index].path;
curr_track.load();
// Update details of the track
track_art.style.backgroundImage =
"url(" + track_list[track_index].image + ")";
track_name.textContent = track_list[track_index].name;
track_artist.textContent = track_list[track_index].artist;
now_playing.textContent =
"PLAYING " + (track_index + 1) + " OF " + track_list.length;
// Set an interval of 1000 milliseconds
// for updating the seek slider
updateTimer = setInterval(seekUpdate, 1000);
// Move to the next track if the current finishes playing
// using the 'ended' event
curr_track.addEventListener("ended", nextTrack);
// Apply a random background color
random_bg_color();
}
// Function to reset all values to their default
function resetValues() {
curr_time.textContent = "00:00";
total_duration.textContent = "00:00";
seek_slider.value = 0;
}
function playpauseTrack() {
// Switch between playing and pausing
// depending on the current state
if (!isPlaying) playTrack();
else pauseTrack();
}
function playTrack() {
// Play the loaded track
curr_track.play();
isPlaying = true;
// Replace icon with the pause icon
playpause_btn.innerHTML = '<i class="fa fa-pause-circle fa-5x"></i>';
}
function pauseTrack() {
// Pause the loaded track
curr_track.pause();
isPlaying = false;
// Replace icon with the play icon
playpause_btn.innerHTML = '<i class="fa fa-play-circle fa-5x"></i>';
}
function nextTrack() {
// Go back to the first track if the
// current one is the last in the track list
if (track_index < track_list.length - 1)
track_index += 1;
else track_index = 0;
// Load and play the new track
loadTrack(track_index);
playTrack();
}
function prevTrack() {
// Go back to the last track if the
// current one is the first in the track list
if (track_index > 0)
track_index -= 1;
else track_index = track_list.length - 1;
// Load and play the new track
loadTrack(track_index);
playTrack();
}
function seekTo() {
// Calculate the seek position by the
// percentage of the seek slider
// and get the relative duration to the track
seekto = curr_track.duration * (seek_slider.value / 100);
// Set the current track position to the calculated seek position
curr_track.currentTime = seekto;
}
function setVolume() {
// Set the volume according to the
// percentage of the volume slider set
curr_track.volume = volume_slider.value / 100;
}
function seekUpdate() {
let seekPosition = 0;
// Check if the current track duration is a legible number
if (!isNaN(curr_track.duration)) {
seekPosition = curr_track.currentTime * (100 / curr_track.duration);
seek_slider.value = seekPosition;
// Calculate the time left and the total duration
let currentMinutes = Math.floor(curr_track.currentTime / 60);
let currentSeconds = Math.floor(curr_track.currentTime - currentMinutes * 60);
let durationMinutes = Math.floor(curr_track.duration / 60);
let durationSeconds = Math.floor(curr_track.duration - durationMinutes * 60);
// Add a zero to the single digit time values
if (currentSeconds < 10) { currentSeconds = "0" + currentSeconds; }
if (durationSeconds < 10) { durationSeconds = "0" + durationSeconds; }
if (currentMinutes < 10) { currentMinutes = "0" + currentMinutes; }
if (durationMinutes < 10) { durationMinutes = "0" + durationMinutes; }
// Display the updated duration
curr_time.textContent = currentMinutes + ":" + currentSeconds;
total_duration.textContent = durationMinutes + ":" + durationSeconds;
}
}
// Load the first track in the tracklist
loadTrack(track_index);
</script>
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |