ViewportConfig: two Reanimated shared values that
the engine adopts as its scroll/zoom state. Updating them moves the chart on the
UI thread, and the chart’s pan/pinch gestures write those same values.
ViewportConfig extends ChartViewportControl (the shared-value pair) with optional
behavior settings. Like the other chart features, pass an object to configure it
or viewport={false} to disable external control; omitted also uses private state.
There is no true shorthand because the two shared values are required. Configuration
preserves those shared values by reference; their contents stay on the UI thread.
A non-null end can be at or beyond the pane’s own live edge, which lets charts with
different forming-candle boundaries share a view. The retained-history guard still
applies: an end before the first point/bar falls back to live without clearing the
shared value. Keep overlapping history in all panes.
Copy the leader’s drawn range
The app decides which pane leads. Keep separate pairs for leader and followers to avoid multiple charts writing the same state. Read the leader’s drawn range throughrenderOverlay, then copy it with useAnimatedReaction. This includes
its window easing and avoids a React render per frame. Disable gestures on a
follower while it is being driven.
windowSmoothing: false on a follower copying scale.window: that width is
already drawn, so easing it again would make the follower trail a pinch or range
change. The leader keeps normal smoothing. This flag affects only non-null window
overrides; value/Y-range smoothing and the return to timeWindow after clearing
the width keep their normal behavior. Separate engines may still publish on
adjacent frames; this API does not promise an atomic render across canvases.
For handoff, stop the old pane’s in-flight gesture/fling, switch the app’s leader
selector, and reverse the copy direction. The new leader’s adopted pair already
contains the prior view. Never leave both mirror directions active at once.
Defaults, reset, and sleep
ChangingtimeWindow, disabling timeScroll, or changing overscroll settings does
not clear a supplied viewport. A non-null width overrides the new base window.
An external end remains honored when scroll gestures are disabled. Gesture bounds
still apply when the user actively pans or pinches that chart.
ref.current?.resetZoom() nulls the supplied pair. The chart then returns to its
configured width and live edge (a paused chart remains paused). In a sync group,
reset the leader and let the mirror carry its drawn return into the followers.
Clearing only a follower will be overwritten by its next leader update.
autoSleep observes both supplied shared values, so a settled follower wakes when
the leader moves. For idle testing, turn pulse off and freeze the data feed/clock;
live scrolling or changing feeds can keep an engine awake.
Clock mapping belongs to the app
All times and widths use the chart’s time coordinate system. Panes using unix seconds can copy directly. If your app compresses session gaps into index time, map the visible edges into the follower’s coordinate system before writing its pair. The library does not infer market sessions or match bars between panes. If the mapping is nonlinear, convert both left and right edges and subtract to get the follower’s width.Try the demo
The example app’s Synced charts screen uses one simulated instrument for 1m and 15m candles. Choose either leader, pan or pinch, switch leaders, and reset both. Turn off Immediate follower width to compare the extra easing. Freeze the feed and clock, wait for zero engine ticks, then move the leader to wake both panes. Changing the base window while zoomed demonstrates that the adopted width persists. Source:app/demo/synced-charts.tsx.
Switch leaders, pinch, change the base window, reset, then freeze the feed