weirsoe-ui.js: mobile drag lifts a floating clone + wider auto-scroll zone
Touch drag now lifts the card into a position:fixed .wt-drag-clone (shadow + scale) that follows the finger, with a dimmed placeholder reordering underneath — reads as actually moving the card. Edge auto-scroll zone widened to 130px with a minimum speed so it reliably scrolls on mobile.
This commit is contained in:
+9
-1
@@ -170,7 +170,15 @@ body::before {
|
||||
}
|
||||
.drag-handle:active { cursor: grabbing; }
|
||||
[data-wt-sortable] > [data-item-id] { cursor: default; }
|
||||
.wt-dragging { opacity: 0.45; }
|
||||
.wt-dragging { opacity: 0.4; }
|
||||
/* The floating clone that follows the finger on touch (the "popped-out" card). */
|
||||
.wt-drag-clone {
|
||||
position: fixed; left: 0; top: 0; z-index: 9999;
|
||||
margin: 0 !important; pointer-events: none; will-change: transform;
|
||||
border-radius: var(--wt-radius);
|
||||
box-shadow: 0 18px 46px #000000aa;
|
||||
opacity: 0.98; transition: none;
|
||||
}
|
||||
|
||||
/* Pill chip / tag-link (e.g. blog tags) */
|
||||
.wt-chip {
|
||||
|
||||
+35
-13
@@ -95,10 +95,12 @@
|
||||
else container.insertBefore(dragEl, after);
|
||||
});
|
||||
|
||||
// ---- mobile: long-press to lift, drag to reorder, edge auto-scroll ----
|
||||
// (native DnD doesn't fire on touch). Hold ~220ms to lift; a scroll-intent
|
||||
// move before that cancels the lift so the page still scrolls normally.
|
||||
var holdTimer = null, lifted = false, touchEl = null, startY = 0, scrollSpeed = 0, raf = null;
|
||||
// ---- mobile: long-press lifts the card into a floating clone that follows
|
||||
// the finger; the list reorders underneath; holding near a screen edge
|
||||
// auto-scrolls. (Native DnD doesn't fire on touch.) Hold ~220ms to lift; a
|
||||
// scroll-intent move before that cancels the lift so the page scrolls. ----
|
||||
var holdTimer = null, lifted = false, touchEl = null, clone = null;
|
||||
var startY = 0, offX = 0, offY = 0, scrollSpeed = 0, raf = null;
|
||||
|
||||
function startScroll() {
|
||||
if (raf) return;
|
||||
@@ -109,8 +111,24 @@
|
||||
raf = requestAnimationFrame(tick);
|
||||
}
|
||||
function stopScroll() { if (raf) { cancelAnimationFrame(raf); raf = null; } scrollSpeed = 0; }
|
||||
|
||||
function makeClone(el, x, y) {
|
||||
var r = el.getBoundingClientRect();
|
||||
offX = x - r.left; offY = y - r.top;
|
||||
clone = el.cloneNode(true);
|
||||
clone.classList.remove('wt-dragging');
|
||||
clone.classList.add('wt-drag-clone');
|
||||
clone.style.width = r.width + 'px';
|
||||
clone.style.transform = 'translate(' + (x - offX) + 'px,' + (y - offY) + 'px) scale(1.04)';
|
||||
document.body.appendChild(clone);
|
||||
}
|
||||
function moveClone(x, y) {
|
||||
if (clone) clone.style.transform = 'translate(' + (x - offX) + 'px,' + (y - offY) + 'px) scale(1.04)';
|
||||
}
|
||||
function endTouch() {
|
||||
if (holdTimer) { clearTimeout(holdTimer); holdTimer = null; }
|
||||
if (clone && clone.parentNode) clone.parentNode.removeChild(clone);
|
||||
clone = null;
|
||||
if (lifted && touchEl) { touchEl.classList.remove('wt-dragging'); persist(container); }
|
||||
lifted = false; touchEl = null; stopScroll();
|
||||
}
|
||||
@@ -118,11 +136,13 @@
|
||||
container.querySelectorAll('[data-item-id]').forEach(function (el) {
|
||||
el.addEventListener('touchstart', function (e) {
|
||||
if (e.touches.length !== 1) return;
|
||||
// don't hijack taps on interactive controls
|
||||
if (e.target.closest('a, button, input, select, textarea, summary, label')) return;
|
||||
startY = e.touches[0].clientY;
|
||||
var t = e.touches[0];
|
||||
startY = t.clientY;
|
||||
holdTimer = setTimeout(function () {
|
||||
lifted = true; touchEl = el; el.classList.add('wt-dragging');
|
||||
lifted = true; touchEl = el;
|
||||
el.classList.add('wt-dragging');
|
||||
makeClone(el, t.clientX, t.clientY);
|
||||
if (navigator.vibrate) navigator.vibrate(12);
|
||||
startScroll();
|
||||
}, 220);
|
||||
@@ -137,14 +157,16 @@
|
||||
return;
|
||||
}
|
||||
if (!touchEl) return;
|
||||
e.preventDefault(); // we own the gesture; stop the page from scrolling under us
|
||||
var y = e.touches[0].clientY;
|
||||
var after = afterElement(container, y);
|
||||
e.preventDefault(); // we own the gesture now
|
||||
var t = e.touches[0];
|
||||
moveClone(t.clientX, t.clientY);
|
||||
var after = afterElement(container, t.clientY);
|
||||
if (after == null) container.appendChild(touchEl);
|
||||
else container.insertBefore(touchEl, after);
|
||||
var edge = 90, vh = window.innerHeight;
|
||||
if (y < edge) scrollSpeed = -Math.ceil((edge - y) / 5);
|
||||
else if (y > vh - edge) scrollSpeed = Math.ceil((y - (vh - edge)) / 5);
|
||||
// edge auto-scroll — generous zone so it triggers well before the edge
|
||||
var edge = 130, vh = window.innerHeight;
|
||||
if (t.clientY < edge) scrollSpeed = -Math.max(6, Math.ceil((edge - t.clientY) / 4));
|
||||
else if (t.clientY > vh - edge) scrollSpeed = Math.max(6, Math.ceil((t.clientY - (vh - edge)) / 4));
|
||||
else scrollSpeed = 0;
|
||||
}, { passive: false });
|
||||
|
||||
|
||||
Reference in New Issue
Block a user