Add mouse drag-to-scroll in the coverflow and a themed custom scrollbar
Coverflow cards can now be grabbed and dragged with the mouse; touch keeps native momentum scrolling. Pointer capture only engages after real movement so ordinary clicks on card buttons still land, a capture-phase click handler swallows exactly the one click that ends a drag, and on release the row glides to the nearest card before snap re-engages. The native horizontal scrollbar under strip and coverflow is replaced by a slim centered track with a glowing brand-green thumb - draggable, click-to-jump, and hidden automatically when everything fits. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
b46042d71d
commit
ddb8391cfb
1 changed files with 16 additions and 5 deletions
|
|
@ -341,23 +341,34 @@ export default function ModelPage() {
|
||||||
if (best !== null) el.scrollTo({ left: best - el.clientWidth / 2, behavior: 'smooth' });
|
if (best !== null) el.scrollTo({ left: best - el.clientWidth / 2, behavior: 'smooth' });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// WICHTIG: Pointer-Capture erst ab echter Bewegung (>4px) starten - sofortiges
|
||||||
|
// Capture beim Druecken wuerde auch das Click-Event auf den Container umlenken,
|
||||||
|
// womit normale Klicks auf Buttons/Links in den Karten nie ankaemen.
|
||||||
|
let pending = false;
|
||||||
const onDown = (e) => {
|
const onDown = (e) => {
|
||||||
if (e.pointerType !== 'mouse' || e.button !== 0) return;
|
if (e.pointerType !== 'mouse' || e.button !== 0) return;
|
||||||
dragging = true;
|
pending = true;
|
||||||
|
dragging = false;
|
||||||
moved = 0;
|
moved = 0;
|
||||||
startX = e.clientX;
|
startX = e.clientX;
|
||||||
startScroll = el.scrollLeft;
|
startScroll = el.scrollLeft;
|
||||||
el.setPointerCapture(e.pointerId);
|
|
||||||
el.style.scrollSnapType = 'none';
|
|
||||||
el.dataset.dragging = 'true';
|
|
||||||
};
|
};
|
||||||
const onMove = (e) => {
|
const onMove = (e) => {
|
||||||
if (!dragging) return;
|
if (!pending && !dragging) return;
|
||||||
const dx = e.clientX - startX;
|
const dx = e.clientX - startX;
|
||||||
moved = Math.max(moved, Math.abs(dx));
|
moved = Math.max(moved, Math.abs(dx));
|
||||||
|
if (!dragging) {
|
||||||
|
if (moved <= 4) return;
|
||||||
|
dragging = true;
|
||||||
|
pending = false;
|
||||||
|
el.setPointerCapture(e.pointerId);
|
||||||
|
el.style.scrollSnapType = 'none';
|
||||||
|
el.dataset.dragging = 'true';
|
||||||
|
}
|
||||||
el.scrollLeft = startScroll - dx;
|
el.scrollLeft = startScroll - dx;
|
||||||
};
|
};
|
||||||
const onUp = (e) => {
|
const onUp = (e) => {
|
||||||
|
pending = false;
|
||||||
if (!dragging) return;
|
if (!dragging) return;
|
||||||
dragging = false;
|
dragging = false;
|
||||||
el.dataset.dragging = 'false';
|
el.dataset.dragging = 'false';
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue