aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIndrajith K L2022-11-25 03:28:07 +0530
committerIndrajith K L2022-11-25 03:28:07 +0530
commit3573342b8fd77ad7ea84b3037e9ffe520173e3a2 (patch)
tree54eae262997c9c5a0676111faa6e040d671a26e7
downloadretrowave-player-3573342b8fd77ad7ea84b3037e9ffe520173e3a2.tar.gz
retrowave-player-3573342b8fd77ad7ea84b3037e9ffe520173e3a2.tar.bz2
retrowave-player-3573342b8fd77ad7ea84b3037e9ffe520173e3a2.zip
Initial Commit
TODO: Keyboard Navigation
-rw-r--r--.jshintrc3
-rw-r--r--README.md7
-rw-r--r--hg.css182
-rw-r--r--index.html37
-rw-r--r--player.js145
5 files changed, 374 insertions, 0 deletions
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 @@
+<!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> \ 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);
+ }
+})();