fix some player UI layout issues

This commit is contained in:
Armin 2026-07-09 00:49:19 +02:00
commit 484ec2abb5

View file

@ -28,7 +28,7 @@ canvas { width: 100%; height: 100px; border-radius: 6px; display: block; }
.cover-art .no-cover { font-size: 40px; color: #6b7089; user-select: none; } .cover-art .no-cover { font-size: 40px; color: #6b7089; user-select: none; }
.player-right { display: flex; flex-direction: column; width: 360px; flex-shrink: 0; align-items: center; } .player-right { display: flex; flex-direction: column; width: 360px; flex-shrink: 0; align-items: center; }
.audio-info { font-size: 11px; color: #6b7089; font-variant-numeric: tabular-nums; min-height: 1.4em; } .audio-info { font-size: 11px; color: #6b7089; font-variant-numeric: tabular-nums; min-height: 1.4em; }
.player .track-info { margin-bottom: 4px; } .player .track-info { margin-bottom: 4px; align-self: flex-end; }
.player .track-info .title { font-size: 16px; font-weight: 600; color: #c6c8d1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .player .track-info .title { font-size: 16px; font-weight: 600; color: #c6c8d1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.player .track-info .artist-name { font-size: 12px; color: #6b7089; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .player .track-info .artist-name { font-size: 12px; color: #6b7089; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.big-time { font-size: 28px; font-weight: 200; color: #d2d4de; letter-spacing: 1px; font-variant-numeric: tabular-nums; margin-bottom: 6px; font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace; } .big-time { font-size: 28px; font-weight: 200; color: #d2d4de; letter-spacing: 1px; font-variant-numeric: tabular-nums; margin-bottom: 6px; font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace; }
@ -36,7 +36,7 @@ canvas { width: 100%; height: 100px; border-radius: 6px; display: block; }
.canvas-area { display: flex; flex-direction: column; flex: 1; min-width: 200px; gap: 6px; margin-right: 16px; } .canvas-area { display: flex; flex-direction: column; flex: 1; min-width: 200px; gap: 6px; margin-right: 16px; }
.progress-row { display: flex; align-items: center; gap: 8px; font-size: 11px; color: #6b7089; font-variant-numeric: tabular-nums; font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace; } .progress-row { display: flex; align-items: center; gap: 8px; font-size: 11px; color: #6b7089; font-variant-numeric: tabular-nums; font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace; }
.waveform-wrap { flex: 1; min-width: 0; cursor: pointer; position: relative; height: 42px; } .waveform-wrap { flex: 1; min-width: 0; cursor: pointer; position: relative; height: 42px; }
.waveform-wrap canvas { display: block; width: 100%; height: 42px; } .waveform-wrap canvas { display: block; width: 100%; height: 42px; filter: drop-shadow(0 1px 1px rgba(0,0,0,0.3)); }
#noiz-overlay { position: fixed; opacity: 0.75; inset: 0; display: flex; justify-content: center; align-items: center; background: transparent; pointer-events: none; z-index: 9999; animation: fadeout 750ms ease 750ms forwards; } #noiz-overlay { position: fixed; opacity: 0.75; inset: 0; display: flex; justify-content: center; align-items: center; background: transparent; pointer-events: none; z-index: 9999; animation: fadeout 750ms ease 750ms forwards; }
#noiz-overlay img { max-width: 50vw; max-height: 50vh; filter: drop-shadow(0 8px 16px rgba(0,0,0,0.5)); } #noiz-overlay img { max-width: 50vw; max-height: 50vh; filter: drop-shadow(0 8px 16px rgba(0,0,0,0.5)); }
@keyframes fadeout { from { opacity: 0.75; transform: scale(1); } to { opacity: 0; transform: scale(1.75); visibility: hidden; } } @keyframes fadeout { from { opacity: 0.75; transform: scale(1); } to { opacity: 0; transform: scale(1.75); visibility: hidden; } }
@ -57,7 +57,7 @@ canvas { width: 100%; height: 100px; border-radius: 6px; display: block; }
.controls .play-btn { width: 44px; height: 44px; background: linear-gradient(to bottom, #91acd1, #84a0c6); color: #161821; font-size: 16px; border: 1px solid #84a0c6; box-shadow: 0 3px 0 #6b88b0, 0 4px 6px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.15); } .controls .play-btn { width: 44px; height: 44px; background: linear-gradient(to bottom, #91acd1, #84a0c6); color: #161821; font-size: 16px; border: 1px solid #84a0c6; box-shadow: 0 3px 0 #6b88b0, 0 4px 6px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.15); }
.controls .play-btn:hover { background: linear-gradient(to bottom, #a0b8db, #91acd1); } .controls .play-btn:hover { background: linear-gradient(to bottom, #a0b8db, #91acd1); }
.controls .play-btn:active { background: linear-gradient(to bottom, #84a0c6, #91acd1); box-shadow: 0 1px 0 #6b88b0, 0 2px 4px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.15); transform: translateY(2px); } .controls .play-btn:active { background: linear-gradient(to bottom, #84a0c6, #91acd1); box-shadow: 0 1px 0 #6b88b0, 0 2px 4px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.15); transform: translateY(2px); }
.volume-row { display: flex; align-items: center; gap: 8px; margin-top: 12px; width: 100%; max-width: 200px; } .volume-row { display: flex; align-items: center; gap: 8px; margin-top: 12px; width: 100%; max-width: 200px; align-self: flex-start; }
.volume-row input[type="range"] { flex: 1; height: 3px; -webkit-appearance: none; appearance: none; background: #272c42; border-radius: 2px; outline: none; } .volume-row input[type="range"] { flex: 1; height: 3px; -webkit-appearance: none; appearance: none; background: #272c42; border-radius: 2px; outline: none; }
.volume-row input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 12px; border-radius: 50%; background: #84a0c6; cursor: pointer; } .volume-row input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 12px; border-radius: 50%; background: #84a0c6; cursor: pointer; }
.volume-row .vol-icon { font-size: 14px; color: #6b7089; } .volume-row .vol-icon { font-size: 14px; color: #6b7089; }
@ -138,11 +138,11 @@ footer .footer-track { flex: 1; min-width: 0; white-space: nowrap; overflow: hid
<div class="canvas-area" id="canvasArea"> <div class="canvas-area" id="canvasArea">
<canvas id="spectrum" width="480" height="200"></canvas> <canvas id="spectrum" width="480" height="200"></canvas>
<div class="progress-row" id="progressRow"> <div class="progress-row" id="progressRow">
<span id="timeCurrent">0:00</span> <span id="timeCurrent">00:00:00</span>
<div class="waveform-wrap" id="waveformWrap"> <div class="waveform-wrap" id="waveformWrap">
<canvas id="waveform"></canvas> <canvas id="waveform"></canvas>
</div> </div>
<span id="timeRemaining">0:00</span> <span id="timeRemaining">00:00:00</span>
</div> </div>
<div style="position:relative"> <div style="position:relative">
<canvas id="vuMeter" width="480" height="20"></canvas> <canvas id="vuMeter" width="480" height="20"></canvas>
@ -155,7 +155,7 @@ footer .footer-track { flex: 1; min-width: 0; white-space: nowrap; overflow: hid
<div class="title" id="trackTitle">Unknown</div> <div class="title" id="trackTitle">Unknown</div>
<div class="artist-name" id="trackArtist">Unknown Artist</div> <div class="artist-name" id="trackArtist">Unknown Artist</div>
</div> </div>
<div class="big-time" id="bigTime">0:00 <span class="sep">/</span> 0:00</div> <div class="big-time" id="bigTime">00:00:00 <span class="sep">/</span> 00:00:00</div>
<div class="controls"> <div class="controls">
<button id="prevBtn" title="Previous">&#9664;&#9664;</button> <button id="prevBtn" title="Previous">&#9664;&#9664;</button>
<button class="play-btn" id="playBtn" title="Play">&#9654;</button> <button class="play-btn" id="playBtn" title="Play">&#9654;</button>
@ -714,8 +714,14 @@ function drawWaveform() {
} }
const y1 = halfH + mn * ampScale; const y1 = halfH + mn * ampScale;
const y2 = halfH + mx * ampScale; const y2 = halfH + mx * ampScale;
ctx.fillStyle = playheadX >= 0 && x < playheadX ? '#6b88b0' : '#84a0c6'; const barH = Math.max(1, y2 - y1);
ctx.fillRect(x, y1, 1, Math.max(1, y2 - y1)); const baseColor = playheadX >= 0 && x < playheadX ? '#6b88b0' : '#84a0c6';
ctx.fillStyle = baseColor;
ctx.fillRect(x, y1, 1, barH);
if (barH >= 3) {
ctx.fillStyle = playheadX >= 0 && x < playheadX ? '#89a2c6' : '#a0b8db';
ctx.fillRect(x, y1, 1, Math.min(2, Math.round(barH * 0.35)));
}
} }
if (playheadX >= 0) { if (playheadX >= 0) {
ctx.strokeStyle = '#e27878'; ctx.strokeStyle = '#e27878';
@ -812,10 +818,11 @@ const GENRES = [
'Christian Rock','Merengue','Salsa','Thrash Metal','Anime','JPop','Synthpop' 'Christian Rock','Merengue','Salsa','Thrash Metal','Anime','JPop','Synthpop'
]; ];
function fmtTime(s) { function fmtTime(s) {
if (!isFinite(s) || s < 0) return '0:00'; if (!isFinite(s) || s < 0) return '00:00:00';
const m = Math.floor(s / 60); const h = Math.floor(s / 3600);
const m = Math.floor((s % 3600) / 60);
const sec = Math.floor(s % 60); const sec = Math.floor(s % 60);
return `${m}:${sec.toString().padStart(2, '0')}`; return `${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}:${sec.toString().padStart(2, '0')}`;
} }
function showError(msg) { function showError(msg) {
errorEl.textContent = msg; errorEl.textContent = msg;