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.

Loading Demo...

#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.

Loading Demo...

#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.

Loading Demo...

#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.

Loading Demo...

#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.

Loading Demo...

#Multiple Annotations

Add multiple ChartAnnotation components to layer independent overlays. Each renders in document order, so later annotations appear on top.

Loading Demo...

#API

#ChartAnnotation

PropTypeDescription
render(context: AnnotationContext) => unknownAnnotation 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.

FieldTypeDescription
widthnumberTotal chart width in pixels
heightnumberTotal chart height in pixels
chartAreaBoxAreaBounding 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
xScaleScaleFunction | nullConverts an X data value to a pixel X coordinate. null on radial and treemap charts
yScaleScaleFunction | nullConverts a Y data value to a pixel Y coordinate. null on radial and treemap charts
getScale((axisId: string) => ScaleFunction | undefined) | nullLook up any axis scale by its registered ID. Use this on multi-axis charts. null on radial and treemap charts
ctxCanvasRenderingContext2D | undefinedCanvas 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
fontFamilystringChart font family, for matching annotation text to the chart
textColorstringTheme-aware text color that matches the chart's default label color
isItemVisible(datasetId: string, index: number) => booleanWhether a specific data point is currently visible (not filtered out by legend toggles)
isDatasetVisible(datasetId: string) => booleanWhether a dataset is currently visible
hoveredItem{ datasetId: string; index: number } | nullThe currently hovered data point, or null when nothing is hovered

#BoxArea

FieldTypeDescription
xnumberLeft edge of the plot area in pixels
ynumberTop edge of the plot area in pixels
widthnumberWidth of the plot area in pixels
heightnumberHeight of the plot area in pixels

#Scale Behavior by Chart Type

Chart TypexScaleyScalegetScalecenter
Bar, Line, Area, Scatterreal scalereal scalereal functionchartArea midpoint
Candlestickreal scale (time)real scalereal functionchartArea midpoint
Heatmapreal scale (band)real scale (band)real functionchartArea midpoint
Pie, Donut, Radar, Polarnullnullnullcircle center
TreemapnullnullnullchartArea midpoint