basic impl.; no websockets yet!
This commit is contained in:
commit
d8aa765bf7
5 changed files with 151 additions and 0 deletions
BIN
public/default-artwork.png
Normal file
BIN
public/default-artwork.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 139 KiB |
23
public/index.html
Normal file
23
public/index.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title></title>
|
||||
<link href="main.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
<div id="music-ticker">
|
||||
<div class="artwork-container">
|
||||
<img src="default-artwork.png" alt="" width="64" height="64" id="artwork">
|
||||
</div>
|
||||
<div id="metadata">
|
||||
<h1 id="title">Unknown Track</h1>
|
||||
<p id="artist-album">Unknown Artist • Unknown Album</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="module" src="main.js"></script>
|
||||
</body>
|
||||
</html>
|
87
public/main.css
Normal file
87
public/main.css
Normal file
|
@ -0,0 +1,87 @@
|
|||
:root {
|
||||
--ticker-width: 600px;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'Inter', sans-serif;
|
||||
background: #888;
|
||||
}
|
||||
|
||||
#music-ticker {
|
||||
/* width: fit-content; */
|
||||
max-width: var(--ticker-width);
|
||||
margin: 32px;
|
||||
padding: 8px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 10px;
|
||||
border-radius: 8px;
|
||||
|
||||
&.outline {
|
||||
border: 1px solid white;
|
||||
outline: 1px solid black;
|
||||
}
|
||||
|
||||
.artwork-container {
|
||||
width: 64px;
|
||||
min-width: 64px;
|
||||
height: 64px;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
|
||||
#metadata {
|
||||
min-width: 0;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
text-shadow: 1px 1px 0 #000a;
|
||||
overflow-x: clip;
|
||||
}
|
||||
|
||||
h1 {
|
||||
width: fit-content;
|
||||
min-width: 0;
|
||||
margin: -2px 0;
|
||||
overflow-x: hidden;
|
||||
white-space: nowrap;
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
p {
|
||||
width: fit-content;
|
||||
min-width: 0;
|
||||
margin: -2px 0;
|
||||
overflow-x: hidden;
|
||||
white-space: nowrap;
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.marquee {
|
||||
animation: 20s ease-in-out infinite marquee;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes marquee {
|
||||
20% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
60% {
|
||||
transform: translateX(calc(-100% + var(--ticker-width) - 74px));
|
||||
}
|
||||
80% {
|
||||
transform: translateX(calc(-100% + var(--ticker-width) - 74px));
|
||||
}
|
||||
}
|
39
public/main.js
Normal file
39
public/main.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
import Stateful from './silver.min.js';
|
||||
|
||||
const musicMeta = new Stateful({
|
||||
artworkURL: 'https://arimelody.space/uploads/musicart/free2play.png',
|
||||
title: 'falling asleep - house version',
|
||||
artist: 'ari melody',
|
||||
album: 'free2play',
|
||||
});
|
||||
|
||||
const elArtwork = document.getElementById('artwork');
|
||||
const elTitle = document.getElementById('title');
|
||||
const elArtistAlbum = document.getElementById('artist-album');
|
||||
const elMetadata = document.getElementById('metadata');
|
||||
|
||||
function setMetadata(artworkURL, title, artist, album) {
|
||||
musicMeta.set({ artworkURL, title, artist, album });
|
||||
}
|
||||
|
||||
document.addEventListener('readystatechange', () => {
|
||||
musicMeta.onUpdate(value => {
|
||||
elArtwork.src = value.artworkURL;
|
||||
elTitle.innerText = value.title;
|
||||
elArtistAlbum.innerText = `${value.artist} • ${value.album}`;
|
||||
document.title = `Now playing: ${value.artist} - ${value.title}`;
|
||||
console.log(`Now playing: ${value.artist} - ${value.title}`);
|
||||
|
||||
const maxWidth = elMetadata.getBoundingClientRect().width;
|
||||
elTitle.classList.remove('marquee');
|
||||
elArtistAlbum.classList.remove('marquee');
|
||||
if (elTitle.getBoundingClientRect().width > maxWidth) {
|
||||
elTitle.classList.add('marquee');
|
||||
}
|
||||
if (elArtistAlbum.getBoundingClientRect().width > maxWidth) {
|
||||
elArtistAlbum.classList.add('marquee');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
window.setMetadata = setMetadata;
|
2
public/silver.min.js
vendored
Normal file
2
public/silver.min.js
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
export default class Stateful{#e;#t=[];constructor(e){this.#e=e}get(){return this.#e}set(e){let t=this.#e;this.#e=e;for(let s in this.#t)this.#t[s](e,t)}update(e){this.set(e(this.#e))}onUpdate(e){return this.#t.push(e),e}removeListener(e){this.#t=this.#t.filter((t=>t!==e))}}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue