The following illustrates basic usage to create an animated line chart with a bottom Axis
, Grid
,
and Tooltip
:
See sections below for more detailed guidance and advanced usage, or explore the comprehensive API
below.
Installation
npm install --save @visx/xychart react-spring
Note: react-spring
is a required peerDependency
for importing Animated*
components.
Series types
The following Series
types are currently supported and we are happy to review or consider
additional Series types in the future.
Component name | Description | Usage |
---|
(Animated)AreaSeries | Connect data points with a <path /> , with a color fill to the zero baseline | <AreaSeries /> |
(Animated)BarSeries | Render a <rect /> for each data point | <BarSeries /> |
(Animated)BarGroup | Group multiple child <BarSeries /> values together | <BarGroup><BarSeries /><BarSeries />...</BarGroup> |
(Animated)BarStack | Stack multiple child <BarSeries /> values together | <BarStack><BarSeries /><BarSeries />...</BarStack> |
(Animated)GlyphSeries | Render a Glyph (any shape, defaults to <circle /> ) for each data point, e.g., a scatter plot | <GlyphSeries renderGlyph={() => ...} /> |
(Animated)LineSeries | Connect data points with a <path> | <GlyphSeries /> |
All Series
have animated and non-animated variants to give you more control over your bundle size,
support missing (null
) data, and can be rendered vertically or horizontally.
Theming
Default lightTheme
and darkTheme
themes are exported from @visx/xychart
and the utility
buildChartTheme
is exported to support easy creation of custom themes.
import { buildTheme, XYChart } from '@visx/xychart';
import { TextProps as SVGTextProps } from '@visx/text/lib/Text';
const customTheme = buildTheme({
backgroundColor: string;
colors: string[];
svgLabelBig?: SVGTextProps;
svgLabelSmall?: SVGTextProps;
htmlLabel?: HTMLTextStyles;
xAxisLineStyles?: LineStyles;
yAxisLineStyles?: LineStyles;
xTickLineStyles?: LineStyles;
yTickLineStyles?: LineStyles;
tickLength: number;
gridColor: string;
gridColorDark: string;
gridStyles?: CSSProperties;
});
() => <XYChart theme={customTheme} />
Tooltips
@visx/tooltip
Tooltip
s are integrated into @visx/xychart
, and should be rendered as a child of
XYChart
(or a child where TooltipContext
is provided).
Tooltip
positioning is handled by the Tooltip
itself, based on TooltipContext
. Tooltip
is rendered inside a Portal
, avoiding clipping by parent DOM elements with higher z-index
contexts. See the API below for a full list of props
to support additional behavior, such as
snapping to data point positions and rendering cross-hairs.
Tooltip
content is controlled by the specified prop.renderTooltip
which has access to:
tooltipData.nearestDatum
– the globally closest Datum
, across all Series
's dataKey
stooltipData.datumByKey
– the closest Datum
for each Series
's dataKey
; this enables
"shared tooltips" where you can render the nearest data point for each Series
.- a shared
colorScale
which maps Series
's dataKey
s to theme
colors
Event handlers
The following PointerEvent
s (handling both MouseEvent
s and TouchEvent
s) are currently
supported. They may be set on individual Series
components (e.g.,
<BarSeries onPointerMove={() => ...} />
), or at the chart level (e.g.,
<XYChart onPointerMove={() => {}} />
) in which case they are invoked once for every *Series
.
To disable event emitting for any Series
set <*Series enableEvents=false />
. The
onFocus/onBlur
handlers enable you to make your chart events and Tooltip
s accessible via
keyboard interaction. Note that the current implementation requires your target browser to support
the SVG 2.0
spec for tabIndex
on SVG
elements.
Below, HandlerParms
has the following type signature:
type EventHandlerParams<Datum> = {
datum: Datum;
distanceX: number;
distanceY;: number;
event: React.PointerEvent | React.FocusEvent;
index: number;
key: string;
svgPoint: { x: number; y: number };
};
Prop name | Signature | XYChart support | *Series support |
---|
onPointerMove | (params: EventHandlerParams<Datum>) => void | ✅ | ✅ |
onPointerOut | (event: React.PointerEvent) => void | ✅ | ✅ |
onPointerUp | (params: EventHandlerParams<Datum>) => void | ✅ | ✅ |
onFocus | (params: EventHandlerParams<Datum>) => void | ❌ | ✅ |
onBlur | (event: React.TouchEvent) => void | ❌ | ✅ |
Annotations
Composable @visx/annotations
annotations are integrated into @visx/xychart
and use its theme and
dimension context. These components allow for annotation of individual points using
AnnotationCircleSubject
, or x- or y-thresholds using AnnotationLineSubject
.
import {
XYChart,
AnimatedAnnotation,
AnnotationLabel,
AnnotationConnector,
AnnotationCircleSubject,
} from '@visx/xychart';
const data = [
{ x: '2020-01-01', y: 50 },
{ x: '2020-01-02', y: 10 },
{ x: '2020-01-03', y: 20 },
];
() => (
<XYChart {...}>
<LineSeries dataKey="line" data={data} xAccessor={...} yAccessor={...} />
<AnimatedAnnotation
dataKey="line" // use this Series's accessor functions, alternatively specify x/yAccessor here
datum={data[0]}
dx={labelXOffset}
dy={labelYOffset}
editable={isEditable}
onDragEnd={({ x, y, dx, dy }) => /** handle edit */}
>
{/** Text label */}
<AnnotationLabel title="My point" subtitle="More deets" />
{/** Draw circle around point */}
<AnnotationCircleSubject />
{/** Connect label to CircleSubject */}
<AnnotationConnector />
</AnimatedAnnotation>
</XYChart>
)
Advanced usage
Examples
XYChart
is implemented using modularized React.context
layers for scales, canvas dimensions,
data, events, and tooltips which enables more advanced usage than many other chart-level
abstractions.
By default XYChart
renders all context providers if a given context is not available, but you can
share context across multiple XYChart
s to implement functionality such as linked tooltips, shared
themes, or shared data.
- 🔜 Custom chart background using theme and chart dimensions
- 🔜 Linked tooltips
- 🔜 Programmatically control tooltips
DataContext
This context provides chart canvas dimensions (width
, height
, and margin
), x/y/color scales,
and a data registry. The data registry includes data from all child *Series
, and x/y/color scales
are updated accordingly accounting for canvas dimensions.
ThemeContext
This context provides an XYChart
theme, its used by all visual elements that compose a chart, and
can be used to render custom visual elements that are on theme.
EventEmitterContext
This context provides an event publishing / subscription object which can be used via the
useEventEmitter
hook. Series
and XYChart
events, including tooltip updates, are emitted and
handled with through this context.
import { useEventEmitter, EventEmitterContext } from '@visx/xychart';
const eventSourceId = 'optional-source-id-filter';
() => (
<EventEmitterContext>
{/** emit events */}
{() => {
const emit = useEventEmitter();
return (
<button onPointerUp={event => emit('pointerup', event, eventSourceId)}>emit event</button>
);
}}
{/** subscribe to events */}
{() => {
const [clickCount, setClickCount] = useState(0);
useEventEmitter('pointerUp', () => setClickCount(clickCount + 1), [eventSourceId]);
return <div>Pressed {clickCount} times</div>;
}}
</EventEmitterContext>
);
TooltipContext
This context provides access to @visx/tooltip
s useTooltip
state, including whether the tooltip
is visible (tooltipOpen
), tooltlip position (tooltipLeft
, tooltipTop
),
tooltipData: { nearestDatum, datumByKey }
described above, and functions to update context
(hideTooltip
, showTooltip
, and updateTooltip
).
⚠️ ResizeObserver
dependency
The Tooltip
and AnnotationLabel
components rely on
ResizeObserver
s. If your
browswer target needs a polyfill, you can either polute the window
object or inject it cleanly
using the resizeObserverPolyfill
prop for these components.
Examples
❌ Error: This browser does not support ResizeObserver out of the box
() => <XYChart {...}><Tooltip /></XYChart>
✅ No errors
() => <XYChart {...}><Tooltip /></XYChart>
import ResizeObserver from 'resize-observer-polyfill';
() => <XYChart {...}><Tooltip /></XYChart>
import ResizeObserver from 'resize-observer-polyfill';
() => (
<XYChart {...}>
<Tooltip resizeObserverPolyfill={ResizeObserver} />
</XYChart>
)