Skip to content

fix(gallery): eliminate marquee ping-pong by direction-aware, phase-continuous wrap - #28

Open
Faych (neverbiasu) wants to merge 1 commit into
microsoft:mainfrom
neverbiasu:fix/carousel-marquee-wrap
Open

fix(gallery): eliminate marquee ping-pong by direction-aware, phase-continuous wrap#28
Faych (neverbiasu) wants to merge 1 commit into
microsoft:mainfrom
neverbiasu:fix/carousel-marquee-wrap

Conversation

@neverbiasu

Copy link
Copy Markdown
Contributor

Summary

The auto-scrolling poster walls (reel-page) and card carousels (idea-page) jittered violently — rows visibly shook left/right every frame instead of drifting smoothly. DevTools showed scrollLeft ping-ponging between 0 and 51528 on consecutive frames.

There were two independent root causes, both fixed here.

Root cause 1 — the wrap checked both edges

// before
if (scrollLeft >= singleWidth)  scrollLeft -= singleWidth;
else if (scrollLeft <= 0)       scrollLeft += singleWidth;

A row travelling right starts at scrollLeft = 0, so it immediately satisfies the lower bound, jumps to the upper bound, which immediately satisfies the upper bound, and jumps back. Ping-pong, every frame.

Fix: each row only checks the edge it is actually travelling toward (dir-aware), and shifts by exactly one period instead of clamping — clamping parks the value right on the other trigger line and leaves a residual offset that accumulates into a visible jump.

Root cause 2 — CSS scroll-behavior: smooth on the track

.wall / .carousel both had scroll-behavior: smooth, so every per-frame scrollLeft write started a competing CSS scroll animation. Removed from both stylesheets; the arrow buttons pass behavior: "smooth" explicitly to scrollBy(), so their UX is unchanged.

Also fixed

  • Loop period was derived from scrollWidth / 2, which includes the track's padding: 44px 32px (~48px error) — every wrap jumped by that delta. Now measured from the DOM: kids[n].offsetLeft - kids[0].offsetLeft.
  • Removed the isResetting lock and the dead-zone guard added in the earlier attempt: they were patches on a wrong model, and the lock swallowed frames.

Files changed

File Change
gallery.js direction-aware, phase-continuous wrap; DOM-measured period
gallery.js same wrap fix; removed stale DEADZONE reference
index.html drop scroll-behavior:smooth from .wall
index.html drop scroll-behavior:smooth from .carousel

Net: +30 / −11, no new dependencies, no behavior change to lightbox / filters / arrows.

Todo

  • Fix bidirectional ping-pong in reel-page marquee
  • Fix single-direction wrap in idea-page carousel
  • Measure the loop period from tile offsetLeft instead of scrollWidth/2
  • Remove scroll-behavior:smooth from .wall and .carousel
  • Remove the obsolete isResetting lock and dead-zone guard
  • Verify no leftover DEADZONE / isResetting / debug logs (grep clean)
  • Static check: no JS errors reported in either file

How to test

cd docs && python3 -m http.server 8000
# open http://localhost:8000/reel-page/  and  http://localhost:8000/idea-page/

…ontinuous wrap

- wrap only on the edge each row travels toward; checking both edges made
  every wrap land on the other edge's trigger, causing per-frame ping-pong
- shift by exactly one period instead of clamping, so the phase stays
  continuous and no residual offset accumulates
- measure the loop period from tile offsetLeft rather than scrollWidth/2,
  which included the track's horizontal padding
- drop scroll-behavior:smooth from .wall/.carousel; CSS smoothing fought the
  per-frame scrollLeft writes (arrow buttons pass behavior explicitly)
- remove the now-unnecessary isResetting lock and dead-zone guard
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant