made changes
This commit is contained in:
parent
7813a44af0
commit
f7cc4c9a5c
4 changed files with 798 additions and 59 deletions
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
body {
|
||||
background-color: #262626;
|
||||
margin: 20px;
|
||||
margin: 1vw;
|
||||
color: #ffffff;
|
||||
overflow: clip;
|
||||
font-family:Work Sans,sans-serif;
|
||||
|
|
@ -14,29 +14,24 @@ body {
|
|||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#title {
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
|
||||
/* --- Left column --- */
|
||||
.song {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#song-image {
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
border-radius: 20px;
|
||||
width: 25vw;
|
||||
height: 25vw;
|
||||
border-radius: 1vw;
|
||||
}
|
||||
|
||||
#song-diff {
|
||||
font-size: 2rem;
|
||||
padding: 16px;
|
||||
min-width: 80px;
|
||||
height: 40px;
|
||||
border-radius: 20px;
|
||||
border: 1px solid black;
|
||||
font-size: 3vh;
|
||||
padding: 0.8vw;
|
||||
min-width: 5vw;
|
||||
height: 2vw;
|
||||
border-radius: 1vw;
|
||||
border: 0.02vw solid black;
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
|
@ -46,7 +41,7 @@ body {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
#song-diff.stale {
|
||||
#song-diff.stale, #song-diff.new {
|
||||
background-color: gray;
|
||||
}
|
||||
|
||||
|
|
@ -58,6 +53,16 @@ body {
|
|||
background-color: red;
|
||||
}
|
||||
|
||||
.current-column {
|
||||
font-size: 2.25vh;
|
||||
}
|
||||
|
||||
.current-column h1 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.current-column h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* --- Middle column --- */
|
||||
.left-divide {
|
||||
|
|
@ -66,18 +71,17 @@ body {
|
|||
}
|
||||
|
||||
.song-stats {
|
||||
margin-left: 100px;
|
||||
margin-left: 2vw;
|
||||
}
|
||||
|
||||
.artist-info p {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
.artist-info {
|
||||
font-size: 2.25vh;
|
||||
}
|
||||
|
||||
|
||||
/* --- Right column --- */
|
||||
#queue {
|
||||
width: 700px;
|
||||
width: 35vw;
|
||||
}
|
||||
|
||||
.queue-item {
|
||||
|
|
@ -86,18 +90,21 @@ body {
|
|||
}
|
||||
|
||||
.queue-item .song-title {
|
||||
font-size: 2rem;
|
||||
margin-left: 20px;
|
||||
font-size: 3vh;
|
||||
margin-left: 1vw;
|
||||
}
|
||||
.queue-item .song-artist {
|
||||
font-size: 1.5rem;
|
||||
margin-left: 20px;
|
||||
font-size: 2.25vh;
|
||||
margin-left: 1vw;
|
||||
color: #ccc;
|
||||
}
|
||||
.queue-item .song-time {
|
||||
text-align: right;
|
||||
margin-right: 10px;
|
||||
font-size: 1.5rem;
|
||||
margin-right: 0.5vw;
|
||||
font-size: 2.25vh;
|
||||
|
||||
justify-content: right;
|
||||
display: flex;
|
||||
gap: 1.5vw;
|
||||
}
|
||||
.queue-right-wrapper {
|
||||
width: 100%;
|
||||
|
|
@ -109,10 +116,17 @@ body {
|
|||
}
|
||||
|
||||
.queue-image {
|
||||
height: 100px;
|
||||
width: 100px;
|
||||
height: 5vw;
|
||||
width: 5vw;
|
||||
}
|
||||
|
||||
.queue-item.playing {
|
||||
background-color: #1a1a1a;
|
||||
}
|
||||
|
||||
.song-diff.queue-risen {
|
||||
color: green;
|
||||
}
|
||||
.song-diff.queue-fallen {
|
||||
color: red;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,16 +15,15 @@
|
|||
<img id="song-image">
|
||||
<div id="song-diff"></div>
|
||||
</div>
|
||||
<h1 id="title"></h1>
|
||||
<h2 id="artist"></h2>
|
||||
<h3 id="position"></h3>
|
||||
</div>
|
||||
|
||||
<div class="song-stats">
|
||||
<canvas id="graph" width=500 height=500></canvas>
|
||||
<canvas id="graph"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div class="artist-info">
|
||||
<h1 id="title"></h1>
|
||||
<h2 id="artist"></h2>
|
||||
<h2>Trivia</h2>
|
||||
<ul>
|
||||
<li id="trivia-songcount"></li>
|
||||
|
|
|
|||
113
public/index.js
113
public/index.js
|
|
@ -1,10 +1,14 @@
|
|||
window.onload = async (e) => {
|
||||
const res = await (await fetch("https://www.nporadio2.nl/api/charts/npo-radio-2-top-2000-van-2025-12-25", {})).json();
|
||||
const res = await (await fetch("/ranking", {})).json();
|
||||
window.ranking = res.positions;
|
||||
|
||||
const offset = +window.location.search.slice(1);
|
||||
window.offset = offset;
|
||||
|
||||
const canvas = document.querySelector('#graph');
|
||||
canvas.width = 0.35 * window.innerWidth;
|
||||
canvas.height = 0.50 * window.innerHeight;
|
||||
|
||||
const now = Date.now() - offset * 1000;
|
||||
const curr = window.ranking.find(it => it.broadcastUnixTime < now);
|
||||
var current = curr.position.current;
|
||||
|
|
@ -30,8 +34,7 @@ function update(curr) {
|
|||
diff.classList = curr.position.type;
|
||||
|
||||
document.querySelector("#title").innerText = curr.track.title;
|
||||
document.querySelector("#artist").innerText = curr.track.artist;
|
||||
document.querySelector("#position").innerText = `Nummer ${curr.position.current}`;
|
||||
document.querySelector("#artist").innerText = `${curr.track.artist} (#${curr.position.current})`;
|
||||
|
||||
getGraph(curr.track.artist, curr.track.title);
|
||||
queue(curr.position.current);
|
||||
|
|
@ -41,19 +44,68 @@ function update(curr) {
|
|||
async function getGraph(artist, title) {
|
||||
const res = await (await fetch(`/graph/${artist.replace("?", "")}/${title}`, {})).json();
|
||||
|
||||
const width = 500;
|
||||
const labelSpace = 50;
|
||||
const barWidth = (width - labelSpace) / res.length;
|
||||
const height = 500;
|
||||
|
||||
const cv = document.querySelector("#graph");
|
||||
const ctx = cv.getContext('2d');
|
||||
|
||||
const width = cv.width;
|
||||
const labelSpace = 100;
|
||||
const barWidth = (width - labelSpace) / res.length;
|
||||
const height = cv.height;
|
||||
const graphHeight = height - 60;
|
||||
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
|
||||
for (let i = 0; i <= 2000; i += 200) {
|
||||
const fraction = (i / 2000) * height;
|
||||
// Dots
|
||||
let minPos = 2001;
|
||||
let maxPos = -1;
|
||||
let minYear = undefined;
|
||||
let maxYear = undefined;
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
const position = res[i].position;
|
||||
if (position != undefined) {
|
||||
if (position < minPos) {
|
||||
minPos = position;
|
||||
minYear = i;
|
||||
}
|
||||
if (position > maxPos) {
|
||||
maxPos = position;
|
||||
maxYear = i;
|
||||
}
|
||||
}
|
||||
|
||||
const fraction = (position / 2000) * graphHeight;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = "white";
|
||||
ctx.arc(labelSpace + barWidth * i + 10, fraction, 2.5, 0, 2*Math.PI);
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
// Min and Max lines
|
||||
for (let p of [minPos, maxPos]) {
|
||||
const fraction = (p / 2000) * graphHeight;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = "#808080";
|
||||
ctx.lineWidth = 1;
|
||||
ctx.moveTo(labelSpace, fraction);
|
||||
ctx.lineTo(width, fraction);
|
||||
ctx.stroke();
|
||||
|
||||
ctx.font = "40px sans-serif";
|
||||
ctx.fillStyle = "#808080";
|
||||
ctx.fillText(p.toString(), 0, fraction);
|
||||
}
|
||||
|
||||
// Y axis
|
||||
for (let i = 200; i <= 2000; i += 200) {
|
||||
const fraction = (i / 2000) * graphHeight;
|
||||
|
||||
const lineDist = 70;
|
||||
if (Math.abs(i-minPos) <= lineDist || Math.abs(i-maxPos) <= lineDist) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = "#808080";
|
||||
|
|
@ -62,27 +114,39 @@ async function getGraph(artist, title) {
|
|||
ctx.lineTo(width, fraction);
|
||||
ctx.stroke();
|
||||
|
||||
ctx.font = "20px sans-serif";
|
||||
ctx.font = "40px sans-serif";
|
||||
ctx.fillStyle = "#808080";
|
||||
ctx.fillText(i.toString(), 0, fraction);
|
||||
}
|
||||
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
const position = res[i].position;
|
||||
const fraction = (position / 2000) * height;
|
||||
// X axis
|
||||
const startYear = 1999;
|
||||
const endYear = 2025;
|
||||
const years = endYear-startYear+1;
|
||||
for (let i of [...new Set([res.findIndex(it => it.position != undefined), minYear, maxYear])]) {
|
||||
const fraction = 10 + labelSpace + (i * (width - labelSpace)) / (years);
|
||||
console.log(fraction)
|
||||
|
||||
let year = (100 + i - 1) % 100;
|
||||
|
||||
// ctx.fillRect(barWidth * i, 0, barWidth, position / 10)
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = "white";
|
||||
ctx.arc(labelSpace + barWidth * i + 10, fraction, 2.5, 0, 2*Math.PI);
|
||||
ctx.fill();
|
||||
ctx.strokeStyle = "#808080";
|
||||
ctx.lineWidth = 1;
|
||||
ctx.moveTo(fraction, 0);
|
||||
ctx.lineTo(fraction, graphHeight);
|
||||
ctx.stroke();
|
||||
|
||||
ctx.font = "40px sans-serif";
|
||||
ctx.fillStyle = "#808080";
|
||||
ctx.fillText(year.toString(), fraction-3, height-10);
|
||||
}
|
||||
|
||||
// Line plot
|
||||
for (let i = 0; i < res.length-1; i++) {
|
||||
const curr = res[i].position;
|
||||
const next = res[i+1].position;
|
||||
const currFraction = (curr / 2000) * height;
|
||||
const nextFraction = (next / 2000) * height;
|
||||
const currFraction = (curr / 2000) * graphHeight;
|
||||
const nextFraction = (next / 2000) * graphHeight;
|
||||
|
||||
// ctx.fillRect(barWidth * i, 0, barWidth, position / 10)
|
||||
ctx.beginPath();
|
||||
|
|
@ -102,14 +166,17 @@ function queue(currPos) {
|
|||
queueEl.innerHTML = "";
|
||||
|
||||
for (const song of upcoming.reverse()) {
|
||||
const broadcastDT = new Date(song.broadcastUnixTime - offset * 1000);
|
||||
const broadcastDT = new Date(song.broadcastUnixTime + offset * 1000);
|
||||
queueEl.innerHTML += `
|
||||
<div class="queue-item${song.position.current == currPos ? " playing" : ""}">
|
||||
<img class="queue-image" src="${song.track.coverUrl}">
|
||||
<div class="queue-right-wrapper">
|
||||
<p class="song-title">${song.track.title}</p>
|
||||
<p class="song-artist">${song.track.artist}</p>
|
||||
<p class="song-time">${broadcastDT.getHours().toString().padStart(2, "0")}:${broadcastDT.getMinutes().toString().padStart(2, "0")}</p>
|
||||
<span class="song-time">
|
||||
<span class="song-diff queue-${song.position.type}">${song.position.label}</span>
|
||||
<span class="song-time">${broadcastDT.getHours().toString().padStart(2, "0")}:${broadcastDT.getMinutes().toString().padStart(2, "0")}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
|
|
@ -132,12 +199,12 @@ async function getTrivia(curr) {
|
|||
if (artistsSongs[0].position == curr.position.current) {
|
||||
document.querySelector("#trivia-first").innerText = `Dit is het hoogste nummer van ${curr.track.artist} in de lijst.`;
|
||||
} else {
|
||||
document.querySelector("#trivia-first").innerText = `Het hoogste nummer van ${curr.track.artist} is ${artistsSongs[0].title}.`;
|
||||
document.querySelector("#trivia-first").innerText = `Het hoogste nummer van ${curr.track.artist} is ${artistsSongs[0].title} (#${artistsSongs[0].position}).`;
|
||||
}
|
||||
|
||||
if (artistsSongs.at(-1).position == curr.position.current) {
|
||||
document.querySelector("#trivia-last").innerText = `Dit is het laagste nummer van ${curr.track.artist} in de lijst.`;
|
||||
} else {
|
||||
document.querySelector("#trivia-last").innerText = `Het laagste nummer van ${curr.track.artist} is ${artistsSongs.at(-1).title}.`;
|
||||
document.querySelector("#trivia-last").innerText = `Het laagste nummer van ${curr.track.artist} is ${artistsSongs.at(-1).title} (#${artistsSongs.at(-1).position}).`;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue