Initial Commit

TODO: Keyboard Navigation
This commit is contained in:
Indrajith K L
2022-11-25 03:28:07 +05:30
commit 3573342b8f
5 changed files with 374 additions and 0 deletions

3
.jshintrc Normal file
View File

@@ -0,0 +1,3 @@
{
"esversion": 6
}

7
README.md Normal file
View File

@@ -0,0 +1,7 @@
### Retrowave Player
A Minimalist Retrowave music player for the web (frontend only).
> This was a challenge to write a minimalist music player using Howler.js in 2 hours limitation was to use only vanilla JS.
Uses: https://retrowave.ru/

182
hg.css Normal file
View File

@@ -0,0 +1,182 @@
#app,
body,
html {
height: 100%;
}
html,
body {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
background: #FAFAFA;
font-family: 'Helvetica Neue', arial, sans-serif;
font-weight: 400;
color: #444;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
background: #f5b7f0;
}
#app {
height: 100%;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.music-player {
width: 350px;
height: 500px;
position: absolute;
top: 50%;
left: 50%;
margin: -250px 0 0 -175px;
overflow: hidden;
border-radius: 10px;
box-shadow: 3px 3px 20px rgba(0, 0, 0, 0.5);
text-align: center;
}
.music-player .color-overlay {
/* Rectangle 11: */
background: rgba(84, 104, 110, 0.4);
width: 350px;
height: 500px;
position: absolute;
z-index: 10;
top: 0;
left: 0;
transition: background 0.3s cubic-bezier(0.33, 0.66, 0.66, 1);
}
.music-player .gradient-overlay {
/* bg-gradient: */
background-image: -webkit-linear-gradient(rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.6) 21%);
background-image: -moz-linear-gradient(rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.6) 21%);
background-image: -o-linear-gradient(rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.6) 21%);
background-image: linear-gradient(rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.6) 21%);
width: 350px;
height: 500px;
position: absolute;
top: 350px;
left: 0;
z-index: 15;
}
.player-controls {
/* width: 100%;
position: absolute;
bottom: 100px;
left: 0;
margin: 0 auto;
padding: 0 50px;
color: #DCE3E7;
font-family: 'Droid Serif', serif;
font-style: 16px;
line-height: 24px;
z-index: 20;
opacity: 0;
transition: bottom 0.3s, opacity 0.3s cubic-bezier(0.33, 0.66, 0.66, 1); */
}
.music-player:hover .player-controls {
opacity: 1;
bottom: 120px;
}
.music-player:hover .color-overlay {
background: rgba(84, 104, 110, 0.8);
}
.title-content {
text-align: center;
margin: 130px 0 0 0;
position: absolute;
z-index: 20;
width: 100%;
top: 0;
left: 0;
}
h3 {
font-size: 24px;
font-weight: 500;
letter-spacing: 2px;
color: #9CC9E3;
font-family: 'Roboto', sans-serif;
margin-bottom: 0;
background: rgb(0 0 0 / 55%);
padding: 10px;
}
hr {
width: 50px;
height: 3px;
margin: 20px auto;
border: 0;
background: #D0BB57;
}
.intro {
width: 170px;
margin: 0 auto;
color: #DCE3E7;
font-family: 'Droid Serif', serif;
font-size: 13px;
font-style: italic;
line-height: 18px;
}
#info {
bottom: 0px;
position: absolute;
right: 8px;
z-index: 999;
color: #ffffff;
margin-bottom: 5px;
cursor: pointer;
}
#history {
bottom: 0px;
position: absolute;
left: 8px;
z-index: 999;
color: #ffffff;
margin-bottom: 5px;
cursor: pointer;
}
dialog {
text-align: center;
padding: 50px;
z-index: 999;
border: 1px solid #000000;
margin-left: 15px;
width: 50%;
background: #000000;
color: #ffffff;
}
dialog button {
background: #ffffff;
border: none;
padding: 3px;
}
dialog::backdrop {
background: repeating-linear-gradient(45deg,
rgba(0, 0, 0, 0.2),
rgba(0, 0, 0, 0.2) 1px,
rgba(0, 0, 0, 0.3) 1px,
rgba(0, 0, 0, 0.3) 20px);
backdrop-filter: blur(3px);
}

37
index.html Normal file
View File

@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Retrowave Player</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/howler/2.2.3/howler.min.js"></script>
<link rel="stylesheet" href="hg.css">
</head>
<body>
<dialog id="dialog">
<p>Welcome to Retrowave Player</p>
<form method="dialog">
<button id="initButton">OK</button>
</form>
</dialog>
<div id="app">
<div class="music-player"
style="background-image: url(&quot;http://retrowave.ru/artwork/ffd65c85c036971075677e76e6b250eef4c6ef2e.jpg&quot;); background-position: 50% 50%; background-repeat: no-repeat;">
<div class="title-content">
<div class="intro">Now Playing</div>
<hr>
<h3 id="track-name">Retrowave Player</h3>
</div>
<div class="gradient-overlay"></div>
<div class="color-overlay"></div>
<div id="history">history</div>
<div id="info">info</div>
</div>
</div>
<script src="player.js"></script>
</body>
</html>

145
player.js Normal file
View File

@@ -0,0 +1,145 @@
(function () {
openDialog();
let isPlaying = false;
let currentTracks = [];
let cursor = 0;
let howerInstance;
const retroWaveRu = "https://retrowave.ru";
getMusic();
let titleEl = document.getElementById("track-name");
let coverArtEl = document.getElementsByClassName("music-player")[0];
coverArtEl.addEventListener("click", () => {
if (howerInstance) {
isPlaying = !isPlaying;
if (isPlaying) {
howerInstance.play();
} else {
howerInstance.pause();
}
}
});
document.getElementById("initButton").addEventListener("click", () => {
playMusic();
});
document.getElementById("history").addEventListener("click", () => {
downloadHistory();
});
document.addEventListener("keyup", (event) => {
const { key } = event;
switch (key) {
case "Space":
break;
case "ArrowLeft":
break;
case "ArrowRight":
break;
}
});
let touchstartX = 0;
let touchendX = 0;
const musixPlayerEl = document.getElementsByClassName("music-player")[0];
if (musixPlayerEl) {
musixPlayerEl.addEventListener("touchstart", (e) => {
touchstartX = e.changedTouches[0].screenX;
});
musixPlayerEl.addEventListener("touchend", (e) => {
touchendX = e.changedTouches[0].screenX;
checkDirection();
});
}
function checkDirection() {
if (touchendX < touchstartX) {
// Swipe Left
}
if (touchendX > touchstartX) {
// Swipe Right
}
}
function openDialog() {
const dialog = document.getElementById("dialog");
dialog.showModal();
}
function getMusic() {
fetch(`https://retrowave.ru/api/v1/tracks?limit=5&cursor=${cursor}`)
.then((res) => res.json())
.then((res) => {
const {
body: { tracks, cursor: currentCursor },
} = res;
cursor = currentCursor;
currentTracks = tracks;
});
}
function initPlayer() { }
function playMusic() {
const currentTrack = currentTracks[0];
const singleTrack = currentTrack.streamUrl;
const fullTrack = `${retroWaveRu}${singleTrack}`;
howerInstance = new Howl({
src: [fullTrack],
html5: true,
onend: function () {
currentTracks.shift();
if (currentTracks.length <= 3) {
getMusic();
}
playMusic();
},
});
isPlaying = true;
updateInfo(currentTrack);
addToHistory(currentTrack);
howerInstance.play();
}
function updateInfo(trackDetails) {
titleEl.innerText = trackDetails.title;
coverArtEl.style.backgroundImage = `url("${retroWaveRu}${trackDetails.artworkUrl}")`;
}
function getHistory() {
let localHistoryStore = localStorage.getItem("retrowave-history") || "[]";
let historyArray = JSON.parse(localHistoryStore);
console.log(historyArray);
return historyArray;
}
function addToHistory(trackDetails) {
let historyArray = getHistory();
historyArray.push(trackDetails);
localStorage.setItem("retrowave-history", JSON.stringify(historyArray));
}
function downloadHistory() {
const historyArray = getHistory();
let element = document.createElement("a");
element.setAttribute(
"href",
"data:application/json;charset=utf-8," +
encodeURIComponent(JSON.stringify(historyArray))
);
element.setAttribute("download", "history.json");
element.style.display = "none";
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
})();