Skip to main content

Crosshair & events

vroom surfaces what the user is looking at back to your app so you can render your own overlays, tooltips, or haptics. The library never plays haptics itself — it just tells you what happened.

Crosshair

The crosshair snaps to the nearest candle and reports it through onCrosshair. It's activated by a long-press on touch and by hovering the mouse on the web. The callback receives a CrosshairEvent:

import * as Haptics from 'expo-haptics';

<VroomChart
candles={candles}
onCrosshair={(e) => {
if (e.reason === 'show' || e.reason === 'move') {
Haptics.selectionAsync();
}
setSelected(e.active ? e.candle : null); // full OHLCV under the crosshair
}}
/>
  • active — whether the crosshair is showing.
  • candle — the Candle under the crosshair (OHLCV), or null when inactive or when the crosshair sits on a future slot (see below).
  • timeMs — the bar-open time (Unix epoch ms) of the slot the crosshair snaps to, or null when inactive. This is set even in the empty space ahead of the most recent candle, so you can read the future time when candle is null.
  • reason'show' (activated), 'move' (snapped to a different slot — one event per slot crossed, not per frame), or 'hide' (dismissed).

Snapping into the future

The crosshair still locks to candles, but it keeps snapping to candle-aligned slots as it moves horizontally into the empty space the chart leaves ahead of the most recent candle. Over real candles, candle holds the OHLCV. On a future slot (where no candle exists yet) candle is null while timeMs reports the slot's time:

onCrosshair={(e) => {
if (!e.active) return clearReadout();
if (e.candle) showOhlcv(e.candle); // over a real candle
else showFutureTime(e.timeMs); // empty slot ahead of the last bar
}}

Use crosshairOffset to lift the dot/horizontal line above the touch point so they aren't hidden under the thumb (default 40px). On the web, a hover crosshair sits directly under the cursor.

Viewport changes

onViewportChange fires when the visible time range changes via gesture, giving you the new window bounds:

<VroomChart
candles={candles}
onViewportChange={(startMs, endMs) => {
// e.g. fetch more candles when the user scrolls into the past
}}
/>

This is the read-side counterpart to the visibleRange prop — see Gestures & viewport.