From 3573342b8fd77ad7ea84b3037e9ffe520173e3a2 Mon Sep 17 00:00:00 2001 From: Indrajith K L Date: Fri, 25 Nov 2022 03:28:07 +0530 Subject: Initial Commit TODO: Keyboard Navigation --- .jshintrc | 3 + README.md | 7 +++ hg.css | 182 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ index.html | 37 +++++++++++++ player.js | 145 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 374 insertions(+) create mode 100644 .jshintrc create mode 100644 README.md create mode 100644 hg.css create mode 100644 index.html create mode 100644 player.js diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..e688987 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,3 @@ +{ + "esversion": 6 +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..b5e949b --- /dev/null +++ b/README.md @@ -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/ \ No newline at end of file diff --git a/hg.css b/hg.css new file mode 100644 index 0000000..46754e5 --- /dev/null +++ b/hg.css @@ -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); +} \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..46d0cc9 --- /dev/null +++ b/index.html @@ -0,0 +1,37 @@ + + + + + + + + Retrowave Player + + + + + + +

Welcome to Retrowave Player

+
+ +
+
+
+
+
+
Now Playing
+
+

Retrowave Player

+
+
+
+
history
+
info
+
+
+ + + + \ No newline at end of file diff --git a/player.js b/player.js new file mode 100644 index 0000000..8cf2151 --- /dev/null +++ b/player.js @@ -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); + } +})(); -- cgit v1.2.3