Recorded on iPhone. Swiped in portrait, then rotated to landscape, where more pages fan out along each edge.
Gesture
Rolling Carousel
Posters ride a surface that rolls away at the screen edges, like film around a spool.
Features
- Cards roll around both edges of the screen, like film over a spool
- A quick swipe keeps its momentum and glides to a stop
- Tap the left or right side to move one card; tap fast to skip ahead
- Can loop forever and play through the cards on its own
- Choose a soft, sharp or default curve, or fine-tune every detail
- Photos show in full at their own shape, never cropped
Built with
- Skia Vertices
- Reanimated worklets
- Gesture Handler
Installation
Usage
Examples
Presets
Change the shape of the fold, then override any single value.
Three across, looping, auto-play
Several cards face-on, an endless strip, and a page every 2.5 seconds.
Driven from outside
Your own buttons and a page counter, with tapping turned off.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
images | DataSourceParam[] | Required | require() or URLs. Keep the array stable; a new array reloads. |
preset | "default" | "soft" | "sharp" | "default" | Shape of the fold: a sharp fold with a small roll, a rounder and broader roll, or a crisp crease. |
loop | boolean | false | After the last page comes the first. |
autoPlay | boolean | false | Move through the pages on a timer. Waits while a finger is down; stops at the last page unless loop is on. |
onIndexChange | (index: number) => void | — | Called as each page change starts. |
config | Partial<RollingCarouselConfig> | — | Fine tuning. See Advanced. |
style | StyleProp<ViewStyle> | — | Fills its parent unless you set a height or flex. |
Advanced
Everything most apps never need to touch.
Every field is optional and overrides the preset.
| Field | Default | Description |
|---|---|---|
cardsPerView | 1 | Cards face-on in the middle. Odd keeps one centred. |
viewWidth | "72%" | Width those cards fill together, in points or a percentage. The rest is folds. |
gap | 16 | Points between cards. |
perspective | 4 | Pages stacked past each fold: 2 → one, 4 → two, 6 → three. |
foldAngle | 89 | Degrees the strip turns at each fold, 0–90. |
foldRadius | 0.25 | Roundness of the fold in card widths. 0 is a crease. |
pageBow | 0.064 | How much each page curves back in the middle. 0 is flat. |
settleDuration | 1200 | Milliseconds a page takes to settle, roughly. |
settleDamping | 0.9 | 1 never overshoots; lower bounces. |
flickLookahead | 0.2 | Seconds of flick speed to look ahead. Higher travels further. |
overscrollResistance | 0.3 | Drag past the ends. 0 is a wall, 1 is free. |
autoPlayInterval | 3000 | Milliseconds each page rests. |
autoPlayStepDuration | 1200 | Milliseconds each step takes. |
autoPlayDirection | "forward" | "forward" or "backward". |
placeholderColors | "auto" | Gradient while an image loads, as two colours. Auto follows dark mode. |
meshColumns | 20 | Smoothness of the page curve. Higher costs more. |
| Method | Description |
|---|---|
next() | One page forward from where it rests or is heading. |
previous() | One page back. |
scrollTo(index, { animated }) | Settle on a page, or jump there with animated: false. With loop, it takes the shorter way round. |
| Prop | Default | Description |
|---|---|---|
initialIndex | 0 | Starting page. Read once; use the ref to move later. |
interactive | true | Off, swiping and tapping do nothing; auto-play, the ref and screen readers still move it. |
tapNavigation | true | Tap the left or right half to move one page. |
accessibilityLabel | "Gallery" | Read before "3 of 8". |
ref | — | A RollingCarouselHandle. See Ref methods. |
- Vertical swipes pass through to a parent ScrollView, so it works inside scrolling screens.
- Quick taps queue up: three taps move three pages.
onIndexChangefires when each move starts, not when it lands. - Cards keep their image's shape and grow as large as they fit. To make them bigger, make the carousel bigger.
- A spinner shows until the first few pages load (at most 4 seconds), then the carousel fades in, so it never appears half-loaded.
- Screen readers read it as "Gallery, 3 of 8", and swiping up or down moves one page.
- With Reduce Motion on, pages move with a short, gentle slide instead of a spring, and auto-play turns off.
How it works
It is one continuous surface, not a row of rotated cards. A mesh is rebuilt every frame in a Reanimated worklet and drawn with Skia, so pages bend smoothly around the fold instead of hinging at a corner. Dragging, the spring and the drawing all run on the UI thread, and nothing redraws while the carousel is still.