Skip to content

Instantly share code, notes, and snippets.

@alpox
Last active May 16, 2021 15:43
Show Gist options
  • Save alpox/b504f66d9e5c422a83c6a51f6d2d97fd to your computer and use it in GitHub Desktop.
Save alpox/b504f66d9e5c422a83c6a51f6d2d97fd to your computer and use it in GitHub Desktop.
useThumbnailRail
const useThumbnailRail = (items, slideChange, active, width) => {
const [springs, api] = useSprings(items.length, i => ({
x: i * getWindowWidth(),
}))
const index = useRef(active)
const lastIndex = useRef(active)
const correct = useCallback(
(i, down) => (result, controller) => {
if (down) return
if (result.value.x > i * width) {
controller.springs.x.stop()
controller.springs.x.start(i * width, {
immediate: false,
config: { decay: false },
})
}
const windowWidth = getWindowWidth()
const targetPosition = (i - items.length) * width + windowWidth
if (result.value.x < targetPosition) {
controller.springs.x.stop()
controller.springs.x.start(targetPosition, {
immediate: false,
config: { decay: false },
})
}
},
[items.length, width]
)
const moveCenter = useCallback(() => {
const windowWidth = getWindowWidth()
api.start(i => {
const pos = (i - index.current) * width + windowWidth / 2 - width / 2
const end = Math.min(
i * width,
Math.max(pos, (i - items.length) * width + windowWidth)
)
return {
x: end,
config: { decay: false },
immediate: lastIndex.current === index.current,
}
})
}, [width, items.length, api])
useEffect(() => {
lastIndex.current = index.current
index.current = active
moveCenter()
}, [active, moveCenter])
const runSprings = useCallback(
(x, mx, down, swipeX, vx) => {
api.start(i => ({
x: i * width + mx,
config:
!down && Math.abs(vx) > 0.5
? { velocity: vx, decay: true, clamp: true, bounce: true }
: {},
immediate: down,
onChange: correct(i, down),
}))
},
[api, correct, width]
)
const drag = useDrag(
({
down,
first,
offset: [x],
movement: [mx],
swipe: [swipeX],
event,
vxvy: [vx],
}) => {
event.stopPropagation()
runSprings(x, mx, down, swipeX, vx, first)
},
{
useTouch: true,
threshold: [5, 0],
initial: () => [springs[0].x.get(), 0],
bounds: { left: -items.length * width + getWindowWidth(), right: 0 },
rubberband: true,
}
)
return { drag, springs }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment