Fix seek bar: tall hit area, correct rail-based rect, prevent scroll during touch drag
This commit is contained in:
@@ -1970,10 +1970,12 @@ const chapterTmpl = `
|
|||||||
|
|
||||||
<!-- Seek bar sits flush on top edge, full width -->
|
<!-- Seek bar sits flush on top edge, full width -->
|
||||||
<div id="seek-track"
|
<div id="seek-track"
|
||||||
class="relative w-full h-1 bg-zinc-800 cursor-pointer touch-none"
|
class="relative w-full cursor-pointer touch-none select-none"
|
||||||
style="display:none">
|
style="display:none">
|
||||||
<div id="seek-fill" class="absolute left-0 top-0 h-full bg-amber-500 pointer-events-none" style="width:0%"></div>
|
<div id="seek-rail" class="absolute left-0 right-0 top-1/2 -translate-y-1/2 h-1 bg-zinc-700 rounded-full overflow-hidden pointer-events-none">
|
||||||
<div id="seek-thumb" class="absolute top-1/2 -translate-y-1/2 w-3 h-3 rounded-full bg-amber-400 shadow pointer-events-none -translate-x-1/2" style="left:0%"></div>
|
<div id="seek-fill" class="absolute left-0 top-0 h-full bg-amber-500" style="width:0%"></div>
|
||||||
|
</div>
|
||||||
|
<div id="seek-thumb" class="absolute top-1/2 -translate-y-1/2 w-3.5 h-3.5 rounded-full bg-amber-400 shadow-md pointer-events-none -translate-x-1/2 transition-transform hover:scale-125" style="left:0%"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Time row (only when playing) -->
|
<!-- Time row (only when playing) -->
|
||||||
@@ -2151,11 +2153,9 @@ const chapterTmpl = `
|
|||||||
.queue-badge-paused { background: #1c1917; color: #d6d3d1; }
|
.queue-badge-paused { background: #1c1917; color: #d6d3d1; }
|
||||||
.queue-badge-error { background: #450a0a; color: #f87171; }
|
.queue-badge-error { background: #450a0a; color: #f87171; }
|
||||||
|
|
||||||
/* Seek bar — expanded touch hit-area without changing visual height */
|
/* Seek bar — tall hit-area, thin visual rail via inner element */
|
||||||
#seek-track {
|
#seek-track {
|
||||||
padding: 6px 0;
|
height: 2.5rem;
|
||||||
margin: -6px 0;
|
|
||||||
box-sizing: content-box;
|
|
||||||
}
|
}
|
||||||
/* Safe-area inset for notched phones */
|
/* Safe-area inset for notched phones */
|
||||||
#mini-player { padding-bottom: env(safe-area-inset-bottom, 0); }
|
#mini-player { padding-bottom: env(safe-area-inset-bottom, 0); }
|
||||||
@@ -2230,6 +2230,7 @@ const chapterTmpl = `
|
|||||||
var chapterListPanel= document.getElementById('chapter-list-panel');
|
var chapterListPanel= document.getElementById('chapter-list-panel');
|
||||||
var chapterListBtn = document.getElementById('chapter-list-btn');
|
var chapterListBtn = document.getElementById('chapter-list-btn');
|
||||||
var seekTrack = document.getElementById('seek-track');
|
var seekTrack = document.getElementById('seek-track');
|
||||||
|
var seekRail = document.getElementById('seek-rail');
|
||||||
var seekFill = document.getElementById('seek-fill');
|
var seekFill = document.getElementById('seek-fill');
|
||||||
var seekThumb = document.getElementById('seek-thumb');
|
var seekThumb = document.getElementById('seek-thumb');
|
||||||
var seekCur = document.getElementById('seek-cur');
|
var seekCur = document.getElementById('seek-cur');
|
||||||
@@ -2269,7 +2270,7 @@ const chapterTmpl = `
|
|||||||
}
|
}
|
||||||
|
|
||||||
function seekFromEvent(e) {
|
function seekFromEvent(e) {
|
||||||
var rect = seekTrack.getBoundingClientRect();
|
var rect = seekRail.getBoundingClientRect();
|
||||||
var clientX = (e.touches ? e.touches[0] : e).clientX;
|
var clientX = (e.touches ? e.touches[0] : e).clientX;
|
||||||
var ratio = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
|
var ratio = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
|
||||||
if (audio.duration && isFinite(audio.duration)) {
|
if (audio.duration && isFinite(audio.duration)) {
|
||||||
@@ -2279,12 +2280,25 @@ const chapterTmpl = `
|
|||||||
}
|
}
|
||||||
(function attachSeek() {
|
(function attachSeek() {
|
||||||
var dragging = false;
|
var dragging = false;
|
||||||
seekTrack.addEventListener('mousedown', function(e){ dragging=true; seekFromEvent(e); e.preventDefault(); });
|
seekTrack.addEventListener('mousedown', function(e) {
|
||||||
seekTrack.addEventListener('touchstart', function(e){ dragging=true; seekFromEvent(e); }, {passive:true});
|
dragging = true;
|
||||||
document.addEventListener('mousemove', function(e){ if(dragging) seekFromEvent(e); });
|
seekFromEvent(e);
|
||||||
document.addEventListener('touchmove', function(e){ if(dragging) seekFromEvent(e); }, {passive:true});
|
e.preventDefault();
|
||||||
document.addEventListener('mouseup', function(){ dragging=false; });
|
});
|
||||||
document.addEventListener('touchend', function(){ dragging=false; });
|
seekTrack.addEventListener('touchstart', function(e) {
|
||||||
|
dragging = true;
|
||||||
|
seekFromEvent(e);
|
||||||
|
}, { passive: true });
|
||||||
|
document.addEventListener('mousemove', function(e) {
|
||||||
|
if (dragging) seekFromEvent(e);
|
||||||
|
});
|
||||||
|
document.addEventListener('touchmove', function(e) {
|
||||||
|
if (dragging) { seekFromEvent(e); e.preventDefault(); }
|
||||||
|
}, { passive: false });
|
||||||
|
document.addEventListener('mouseup', function(e) {
|
||||||
|
if (dragging) { seekFromEvent(e); dragging = false; }
|
||||||
|
});
|
||||||
|
document.addEventListener('touchend', function() { dragging = false; });
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// ── status strip ─────────────────────────────────────────────────────────────
|
// ── status strip ─────────────────────────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user