gtauri viewer: velocity-scaled swipe commit (faster flicks)
Flicks now continue the finger's motion instead of taking a fixed 200 ms: commit duration = remaining distance / release velocity (15 % snappier), clamped 80-240 ms, ease-out. A full-speed flick releasing past half the screen commits in ~80 ms (was 200). Slow releases past the 25 % threshold still settle gently (180 ms smoothstep; 150 ms for keyboard nav). Verified on the emulator: a 100 ms flick is fully settled before the first post-release screencap (~150 ms), with only a 5 px edge artifact between consecutive frames (no residual motion).
This commit is contained in:
parent
ba646fb233
commit
cd31b76889
30
harnesses/gtauri/frontend/dist/index.html
vendored
30
harnesses/gtauri/frontend/dist/index.html
vendored
|
|
@ -546,26 +546,40 @@ function tweenTo(tx, ty, ms, onDone) {
|
|||
/// Both images stay on the page strip for the whole animation:
|
||||
/// the incoming one slides home while the outgoing one slides off
|
||||
/// screen; only then do the roles swap (returns false at the edges).
|
||||
function navigate(delta) {
|
||||
function navigate(delta, vel) {
|
||||
if (tween && tween.commit) return false; // commit already in flight
|
||||
const i = ids.indexOf(viewerId);
|
||||
const ni = i + delta;
|
||||
if (i < 0 || ni < 0 || ni >= ids.length) return false;
|
||||
commitTo(ni, delta);
|
||||
commitTo(ni, delta, vel || 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Commit a swipe: animate vTx to the outgoing offset (the incoming
|
||||
/// preview tracks at vTx + delta*W and lands exactly on 0), then swap
|
||||
/// the elements' roles. The commit tween is locked: input is ignored
|
||||
/// until it finishes (~200 ms).
|
||||
function commitTo(ni, delta) {
|
||||
/// until it finishes. `vel` = release velocity in px/ms: a flick
|
||||
/// continues the finger's motion (duration scales with the remaining
|
||||
/// distance at that velocity, ease-out — fast flicks are fast), a
|
||||
/// slow release settles gently.
|
||||
function commitTo(ni, delta, vel) {
|
||||
navSet(ids[ni], delta); // the incoming (no-op if the drag showed it)
|
||||
const out = -delta * innerWidth;
|
||||
const x0 = vTx, t0 = performance.now(), ms = 200;
|
||||
const x0 = vTx, t0 = performance.now();
|
||||
let ms, ease;
|
||||
if (vel > 0.35) {
|
||||
const remain = Math.abs(out - x0);
|
||||
// Time to cover the remaining distance at the release velocity,
|
||||
// 15 % snappier than the raw continuation, clamped 80–240 ms.
|
||||
ms = Math.max(80, Math.min(240, remain / vel * 0.85));
|
||||
ease = (t) => 1 - Math.pow(1 - t, 3); // ease-out: land soft
|
||||
} else {
|
||||
ms = vel > 0 ? 180 : 150; // drag-settle / keyboard
|
||||
ease = (t) => t * t * (3 - 2 * t);
|
||||
}
|
||||
const step = (now) => {
|
||||
const t = Math.min(1, (now - t0) / ms);
|
||||
const e = t * t * (3 - 2 * t); // smoothstep: pick up, land soft
|
||||
const e = ease(t);
|
||||
vTx = x0 + (out - x0) * e;
|
||||
vTy = 0;
|
||||
applyTransform();
|
||||
|
|
@ -690,9 +704,9 @@ const endPt = (e) => {
|
|||
// Commit past the threshold; at the library edges navigate
|
||||
// refuses (nothing to commit to) and we snap back instead.
|
||||
if (dx < -w * 0.25 || g.vx < -0.35) {
|
||||
if (!navigate(+1)) tweenTo(0, 0, 120, navHide);
|
||||
if (!navigate(+1, Math.abs(g.vx))) tweenTo(0, 0, 120, navHide);
|
||||
} else if (dx > w * 0.25 || g.vx > 0.35) {
|
||||
if (!navigate(-1)) tweenTo(0, 0, 120, navHide);
|
||||
if (!navigate(-1, Math.abs(g.vx))) tweenTo(0, 0, 120, navHide);
|
||||
} else {
|
||||
tweenTo(0, 0, 120, navHide); // not far enough: snap back
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user