Charts - Annotation
Overlay fully custom content on any chart type using SVG nodes or direct Canvas drawing with access to scales, theme colors, and animation.
#Usage
import { ChartAnnotation, ChartSvg } from '@primeui/vue-chart';<ChartSvg>
<!-- series and axes -->
<ChartAnnotation :render="renderFn" />
</ChartSvg>Annotations overlay fully custom content on any chart type. The render callback receives chart area bounds, scale functions, and theme context to position content at specific data values. Return a VNode in SVG mode or draw directly to ctx in Canvas mode.
#Basic
Add ChartAnnotation to render custom content overlaid on the chart area. The render callback receives the chart area bounds, scale functions, and theme context. Use these to position content at specific data values.
#Positioning at Data Values
Use xScale and yScale to convert data values to pixel positions. This is the primary use case: annotating a specific category, timestamp, or value with a label, icon, or shape.
#Multi-Axis Positioning
On charts with multiple Y axes, use getScale('axisId') to retrieve the scale for a specific axis by its registered ID. Use this to position annotations relative to a secondary axis value.
#Radial Charts
On pie, donut, polar, and radar charts xScale, yScale, and getScale are null because there are no cartesian axes. Use center to position content at the chart center and chartArea for the bounding rectangle. This is the standard approach for donut hole labels and polar center annotations.
#Dark Mode
Use textColor for theme-aware text. It is always populated regardless of chart type and already matches the active color scheme, so text adapts to dark mode automatically. The context does not expose a dark-mode flag, so content that is not text (such as an adaptive background fill) detects the scheme on its own, as the demo below does.
#Multiple Annotations
Add multiple ChartAnnotation components to layer independent overlays. Each renders in document order, so later annotations appear on top.
#API
#ChartAnnotation
| Prop | Type | Description |
|---|---|---|
render | (context: AnnotationContext) => unknown | Annotation renderer. SVG: return a VNode. Canvas: draw to ctx and return null |
<ChartAnnotation
:render="
({ xScale, yScale, ctx, textColor }) => {
if (ctx) {
ctx.fillStyle = textColor;
ctx.fillText('Peak', xScale('Jan'), yScale(120) - 8);
return null;
}
return h('text', { x: xScale('Jan'), y: yScale(120) - 8 }, 'Peak');
}
"
/>#AnnotationContext
Passed to the render callback. The same shape is used across all chart types. Fields that don't apply to a chart type are null rather than absent.
| Field | Type | Description |
|---|---|---|
width | number | Total chart width in pixels |
height | number | Total chart height in pixels |
chartArea | BoxArea | Bounding rectangle of the plot area in pixels: { x, y, width, height } |
center | { x: number; y: number } | Center point of the chart in pixels. For radial charts this is the circle center. For cartesian charts this is the midpoint of chartArea |
xScale | ScaleFunction | null | Converts an X data value to a pixel X coordinate. null on radial and treemap charts |
yScale | ScaleFunction | null | Converts a Y data value to a pixel Y coordinate. null on radial and treemap charts |
getScale | ((axisId: string) => ScaleFunction | undefined) | null | Look up any axis scale by its registered ID. Use this on multi-axis charts. null on radial and treemap charts |
ctx | CanvasRenderingContext2D | undefined | Canvas 2D context. Present only in Canvas mode. Drawing uses absolute pixel coordinates, the same space xScale, yScale, center, and chartArea return; it is not translated to the chart area origin. The default fillStyle is textColor |
fontFamily | string | Chart font family, for matching annotation text to the chart |
textColor | string | Theme-aware text color that matches the chart's default label color |
isItemVisible | (datasetId: string, index: number) => boolean | Whether a specific data point is currently visible (not filtered out by legend toggles) |
isDatasetVisible | (datasetId: string) => boolean | Whether a dataset is currently visible |
hoveredItem | { datasetId: string; index: number } | null | The currently hovered data point, or null when nothing is hovered |
#BoxArea
| Field | Type | Description |
|---|---|---|
x | number | Left edge of the plot area in pixels |
y | number | Top edge of the plot area in pixels |
width | number | Width of the plot area in pixels |
height | number | Height of the plot area in pixels |
#Scale Behavior by Chart Type
| Chart Type | xScale | yScale | getScale | center |
|---|---|---|---|---|
| Bar, Line, Area, Scatter | real scale | real scale | real function | chartArea midpoint |
| Candlestick | real scale (time) | real scale | real function | chartArea midpoint |
| Heatmap | real scale (band) | real scale (band) | real function | chartArea midpoint |
| Pie, Donut, Radar, Polar | null | null | null | circle center |
| Treemap | null | null | null | chartArea midpoint |