Scroll-linked
Drive the track from page scroll instead of a finger.
Sometimes the track should not be dragged at all. linkToScroll hands the
offset to the page: as the section travels through the viewport, the track
advances.
import { createPicker, linkToScroll } from 'loopem'
const section = document.getElementById('stages')
const picker = createPicker(section.querySelector('.track'), {
items: steps,
renderItem,
loop: 'clamp',
})
linkToScroll(picker, section)It handles the range math, the clamping, resize, and cleanup, and returns a
{ destroy }. By default the range covers the whole list; { from, to } narrows
it.
That is this page. The section below is three viewports tall with the stage pinned inside it, and its six steps advance as you scroll past.
It turns input off
linkToScroll calls setInteractive(false) and leaves it off.
Turning input off also gives the page its touch back. An interactive track claims one axis of gesture; a driven one claims none, so a thumb dragged over it scrolls as it should.
Give the section room to scroll
Make the section tall and pin the picker inside it:
#stages {
min-height: 220vh;
}
#stages figure {
position: sticky;
top: 5rem;
}Now the picker stays put while the section slides past, and the track advances as it goes. Half a viewport of scrolling per item feels fast and a whole one feels slow. The demo above is at the fast end so it fits on one page.
Tell people it scrolls
Nobody can tell a scroll-driven track from a broken one by looking. The first thing anyone does is try to drag it, and nothing happens.
Give it a visible cue. A progress rail that fills as the section passes answers both “what do I do here” and “how far in am I”.
Driving it from anything else
linkToScroll is a convenience over seek, which is the general form.
picker.setInteractive(false)
picker.seek(2.5) // continuous, in item units: halfway between 2 and 3A timeline, a range input, a gesture library, a WebSocket. Anything that can produce a number can drive the track.