Custom Cursor Rendering
How to render live cursors your way — HTML overlay, Canvas, or SVG.
useCursors() gives you a Record<userId, UserCursor> with each user's current position (normalized 0–1) and metadata. What you do with it is entirely up to you. This guide shows three approaches.
The data you get
Positions are normalized: x: 0 is left edge, x: 1 is right edge, same for y. Multiply by window.innerWidth (or by an element's dimensions) to get pixel coordinates.
Approach 1: HTML overlay
A fixed-position div that covers the whole viewport, with each cursor absolutely positioned inside it. Simple and easy to style.
This approach works well for full-page experiences (dashboards, docs, marketing pages).
Approach 2: Canvas
When you have an HTML5 canvas element, draw cursors directly on it (or on a transparent overlay canvas). Useful for collaborative canvas apps like the demo.
The trick is to track cursor positions relative to the canvas, not the viewport. Normalize against the canvas element's bounding rect instead of window.inner*.
Note that with canvas rendering you may want to turn off the SDK's interpolation (interpolate={false} on the provider) if you're doing your own smoothing, or keep it on to let the SDK handle it for you.
Approach 3: SVG
SVG is a good middle ground — vector rendering with full CSS styling. Works well for diagram editors, flowcharts, or any app already using SVG.
Filtering out-of-bounds cursors
Users who move the mouse outside your tracked area may send sentinel values or last-known positions. A common pattern is to skip cursors with positions outside 0–1:
Interpolation
useCursors runs its own interpolation loop by default (configurable via the interpolate and interpolationMs props on <FlockProvider>). You get already-smoothed positions in the canvas/SVG/HTML approaches above — no extra work needed.
If you want to do your own smoothing (e.g., a spring physics simulation), pass interpolate={false} to get raw received positions and handle the animation yourself.