Chart Annotations in React Chart

27 Aug 202624 minutes to read

Chart annotations let you highlight specific areas of the chart by overlaying text, shapes, images, or custom HTML elements directly inside the chart area. Use annotations to emphasize trends, mark thresholds, call out key data points, or display additional context such as watermarks and footers.

Note: To use the annotation feature, inject the ChartAnnotation module into the chart services.

Getting started

Annotations are added through the annotations option, which accepts an array of AnnotationDirective items wrapped in AnnotationsDirective. Use the content property to specify what is rendered—either a string (rendered as text) or a function/element (rendered as custom HTML).

In addition to content, the following properties control placement:

Property Type Default Description
x string | number 0 Horizontal position. A string matches a category value; a number is interpreted in pixels (default) or data values (when coordinateUnits is Point).
y number 0 Vertical position. Interpreted in pixels or data values based on coordinateUnits.
region 'Chart' | 'Series' 'Chart' Reference space for the x and y values.
coordinateUnits 'Pixel' | 'Point' 'Pixel' Unit used to interpret x and y.

The following example adds a simple text annotation over a column series.

import * as React from "react";
import * as ReactDOM from "react-dom";
import { ChartComponent, SeriesCollectionDirective, SeriesDirective, Inject, ChartAnnotation, AnnotationsDirective, AnnotationDirective, Legend, Category, Tooltip, DataLabel, ColumnSeries } from '@syncfusion/ej2-react-charts';
import { columnData } from './datasource';
function App() {
    const primaryxAxis = { valueType: 'Category', title: 'Countries' };
    const primaryyAxis = { minimum: 0, maximum: 80, interval: 20, title: 'Medals' };
    const border = { width: 2, color: 'grey' };
    const animation = { enable: true, duration: 1200, delay: 100 };
    return <ChartComponent id='charts' primaryXAxis={primaryxAxis} primaryYAxis={primaryyAxis} title='Olympic Medals'>
      <Inject services={[ColumnSeries, Legend, Tooltip, DataLabel, Category, ChartAnnotation]}/>
      <AnnotationsDirective>
        <AnnotationDirective content='70 Gold Medals' region='Series' coordinateUnits='Point' x='Japan' y={75}>
        </AnnotationDirective>
      </AnnotationsDirective>
      <SeriesCollectionDirective>
        <SeriesDirective dataSource={columnData} xName='country' yName='gold' name='Gold' border={border} animation={animation} type='Column'>
        </SeriesDirective>
      </SeriesCollectionDirective>
    </ChartComponent>;
}
;
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));
import * as React from "react";
import * as ReactDOM from "react-dom";
import { AxisModel, ChartComponent, SeriesCollectionDirective, SeriesDirective, Inject, ChartAnnotation, AnnotationsDirective, AnnotationDirective, Legend, Category, Tooltip, DataLabel, ColumnSeries}from'@syncfusion/ej2-react-charts';
import { columnData } from './datasource';

function App() {

  const primaryxAxis: AxisModel = { valueType: 'Category', title: 'Countries' };
  const primaryyAxis: AxisModel = { minimum: 0, maximum: 80, interval: 20, title: 'Medals' };
  const border = { width: 2, color: 'grey' };
  const animation = { enable: true, duration: 1200, delay: 100 };

  return <ChartComponent id='charts'
      primaryXAxis={primaryxAxis}
      primaryYAxis={primaryyAxis}
      title='Olympic Medals'>
      <Inject services={[ColumnSeries, Legend, Tooltip, DataLabel, Category, ChartAnnotation]} />
      <AnnotationsDirective>
        <AnnotationDirective content='70 Gold Medals' region='Series' coordinateUnits='Point' x='Japan' y={75}>
        </AnnotationDirective>
      </AnnotationsDirective>
      <SeriesCollectionDirective>
        <SeriesDirective dataSource={columnData} xName='country' yName='gold' name='Gold'
          border={border}
          animation={animation} type='Column'>
        </SeriesDirective>
      </SeriesCollectionDirective>
    </ChartComponent>

};
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));
export let columnData = [
    { country: "USA",       gold: 50 },
    { country: "China",     gold: 40 },
    { country: "Japan",     gold: 70 },
    { country: "Australia", gold: 60 },
    { country: "France",    gold: 50 },
    { country: "Germany",   gold: 40 },
    { country: "Italy",     gold: 40 },
    { country: "Sweden",    gold: 30 }
];
export let columnData: Object[] = [
    { country: "USA",       gold: 50 },
    { country: "China",     gold: 40 },
    { country: "Japan",     gold: 70 },
    { country: "Australia", gold: 60 },
    { country: "France",    gold: 50 },
    { country: "Germany",   gold: 40 },
    { country: "Italy",     gold: 40 },
    { country: "Sweden",    gold: 30 }
];

Region

Use the region property to choose the reference space for the annotation’s x and y values:

  • Chart (default) – x and y are positioned relative to the overall chart area. The annotation stays fixed as the data changes.
  • Seriesx and y are positioned relative to a specific series. When coordinateUnits is Point, x is matched to a data point on the series.

The following example uses region: 'Series' with coordinateUnits: 'Point' to anchor the annotation to the Japan data point of the column series.

import * as React from "react";
import * as ReactDOM from "react-dom";
import { ChartComponent, SeriesCollectionDirective, SeriesDirective, Inject, ChartAnnotation, AnnotationsDirective, AnnotationDirective, Legend, Category, Tooltip, DataLabel, ColumnSeries } from '@syncfusion/ej2-react-charts';
import { columnData } from './datasource';
function App() {
    const primaryxAxis = { valueType: 'Category', title: 'Countries' };
    const primaryyAxis = { minimum: 0, maximum: 80, interval: 20, title: 'Medals' };
    const border = { width: 2, color: 'grey' };
    const animation = { enable: true, duration: 1200, delay: 100 };
    const template = chartTemplate;
    function chartTemplate() {
        return (<div className='template'>
      <div>Highest Medal Count</div>
    </div>);
    }
    return <ChartComponent id='charts' primaryXAxis={primaryxAxis} primaryYAxis={primaryyAxis} title='Olympic Medals'>
      <Inject services={[ColumnSeries, Legend, Tooltip, DataLabel, Category, ChartAnnotation]}/>
      <AnnotationsDirective>
        <AnnotationDirective content={template} region='Series' coordinateUnits='Point' x='Japan' y={75}>
        </AnnotationDirective>
      </AnnotationsDirective>
      <SeriesCollectionDirective>
        <SeriesDirective dataSource={columnData} xName='country' yName='gold' name='Gold' border={border} animation={animation} type='Column'>
        </SeriesDirective>
      </SeriesCollectionDirective>
    </ChartComponent>;
}
;
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));
import * as React from "react";
import * as ReactDOM from "react-dom";
import { AxisModel, ChartComponent, SeriesCollectionDirective, SeriesDirective, Inject, ChartAnnotation, AnnotationsDirective, AnnotationDirective, Legend, Category, Tooltip, DataLabel, ColumnSeries} from'@syncfusion/ej2-react-charts';
import { columnData } from './datasource';

function App() {

  const primaryxAxis: AxisModel = { valueType: 'Category', title: 'Countries' };
  const primaryyAxis: AxisModel = { minimum: 0, maximum: 80, interval: 20, title: 'Medals' };
  const border = { width: 2, color: 'grey' };
  const animation = { enable: true, duration: 1200, delay: 100 };
  const template: any = chartTemplate;
  function chartTemplate(): any {
    return (<div className='template'>
      <div>Highest Medal Count</div>
    </div>);
  }

  return <ChartComponent id='charts'
      primaryXAxis={primaryxAxis}
      primaryYAxis={primaryyAxis}
      title='Olympic Medals'>
      <Inject services={[ColumnSeries, Legend, Tooltip, DataLabel, Category, ChartAnnotation]} />
      <AnnotationsDirective>
        <AnnotationDirective content={template} region='Series' coordinateUnits='Point' x='Japan' y={75}>
        </AnnotationDirective>
      </AnnotationsDirective>
      <SeriesCollectionDirective>
        <SeriesDirective dataSource={columnData} xName='country' yName='gold' name='Gold'
          border={border}
          animation={animation} type='Column'>
        </SeriesDirective>
      </SeriesCollectionDirective>
    </ChartComponent>

};
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));
export let columnData = [
    { country: "USA",       gold: 50 },
    { country: "China",     gold: 40 },
    { country: "Japan",     gold: 70 },
    { country: "Australia", gold: 60 },
    { country: "France",    gold: 50 },
    { country: "Germany",   gold: 40 },
    { country: "Italy",     gold: 40 },
    { country: "Sweden",    gold: 30 }
];
export let columnData: Object[] = [
    { country: "USA",       gold: 50 },
    { country: "China",     gold: 40 },
    { country: "Japan",     gold: 70 },
    { country: "Australia", gold: 60 },
    { country: "France",    gold: 50 },
    { country: "Germany",   gold: 40 },
    { country: "Italy",     gold: 40 },
    { country: "Sweden",    gold: 30 }
];

Coordinate Units

Use the coordinateUnits property to choose how the annotation’s x and y values are interpreted:

  • Pixel (default) – x and y are treated as fixed pixel offsets from the top-left corner of the chart area. The annotation does not move with the data.
  • Pointx and y are treated as data values on the chart axes. x matches an axis value (a category name for category axes, a numeric value for numeric/datetime axes) and y matches a series value. The annotation moves with the data.

The following example renders a custom HTML annotation at a fixed pixel location on the chart.

import * as React from "react";
import * as ReactDOM from "react-dom";
import { ChartComponent, SeriesCollectionDirective, SeriesDirective, Inject, ChartAnnotation, AnnotationsDirective, AnnotationDirective, Legend, Category, Tooltip, DataLabel, ColumnSeries } from '@syncfusion/ej2-react-charts';
import { columnData } from './datasource';
function App() {
    const primaryxAxis = { valueType: 'Category', title: 'Countries' };
    const primaryyAxis = { minimum: 0, maximum: 80, interval: 20, title: 'Medals' };
    const border = { width: 2, color: 'grey' };
    const animation = { enable: true, duration: 1200, delay: 100 };
    const template = chartTemplate;
    function chartTemplate() {
        return (<div className='charttemplate'>
      <div> Annotation In Pixel </div>
    </div>);
    }
    return <ChartComponent id='charts' primaryXAxis={primaryxAxis} primaryYAxis={primaryyAxis} title='Olympic Medals'>
      <Inject services={[ColumnSeries, Legend, Tooltip, DataLabel, Category, ChartAnnotation]}/>
      <AnnotationsDirective>
        <AnnotationDirective content={template} coordinateUnits='Pixel' x={150} y={50}>
        </AnnotationDirective>
      </AnnotationsDirective>
      <SeriesCollectionDirective>
        <SeriesDirective dataSource={columnData} xName='country' yName='gold' name='Gold' border={border} animation={animation} type='Column'>
        </SeriesDirective>
      </SeriesCollectionDirective>
    </ChartComponent>;
}
;
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));
import * as React from "react";
import * as ReactDOM from "react-dom";
import { AxisModel,ChartComponent, SeriesCollectionDirective, SeriesDirective, Inject, ChartAnnotation, AnnotationsDirective, AnnotationDirective, Legend, Category, Tooltip, DataLabel, ColumnSeries}from'@syncfusion/ej2-react-charts';
import { columnData } from './datasource';

function App() {

  const primaryxAxis: AxisModel = { valueType: 'Category', title: 'Countries' };
  const primaryyAxis: AxisModel = { minimum: 0, maximum: 80, interval: 20, title: 'Medals' };
  const border = { width: 2, color: 'grey' };
  const animation = { enable: true, duration: 1200, delay: 100 };
  const template: any = chartTemplate;
  function chartTemplate(): any {
    return (<div className='charttemplate'>
      <div> Annotation In Pixel </div>
    </div>);
  }

  return <ChartComponent id='charts'
      primaryXAxis={primaryxAxis}
      primaryYAxis={primaryyAxis}
      title='Olympic Medals'>
      <Inject services={[ColumnSeries, Legend, Tooltip, DataLabel, Category, ChartAnnotation]} />
      <AnnotationsDirective>
        <AnnotationDirective content={template}
          coordinateUnits='Pixel' x={150} y={50}>
        </AnnotationDirective>
      </AnnotationsDirective>
      <SeriesCollectionDirective>
        <SeriesDirective dataSource={columnData} xName='country' yName='gold' name='Gold'
          border={border}
          animation={animation} type='Column'>
        </SeriesDirective>
      </SeriesCollectionDirective>
    </ChartComponent>

};
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));
export let columnData = [
    { country: "USA",       gold: 50 },
    { country: "China",     gold: 40 },
    { country: "Japan",     gold: 70 },
    { country: "Australia", gold: 60 },
    { country: "France",    gold: 50 },
    { country: "Germany",   gold: 40 },
    { country: "Italy",     gold: 40 },
    { country: "Sweden",    gold: 30 }
];
export let columnData: Object[] = [
    { country: "USA",       gold: 50 },
    { country: "China",     gold: 40 },
    { country: "Japan",     gold: 70 },
    { country: "Australia", gold: 60 },
    { country: "France",    gold: 50 },
    { country: "Germany",   gold: 40 },
    { country: "Italy",     gold: 40 },
    { country: "Sweden",    gold: 30 }
];

Customization

The ChartAnnotationSettingsModel exposes additional properties to align and style annotations. The commonly used ones are:

  • horizontalAlignment'Near', 'Center', or 'Far'. Aligns the annotation horizontally relative to its anchor point.
  • verticalAlignment'Top', 'Middle', or 'Bottom'. Aligns the annotation vertically relative to its anchor point.
  • offset{ x: number, y: number }. Shifts the annotation from its anchor point in pixels.
  • opacitynumber between 0 and 1. Sets the opacity of the annotation.

The following snippet customizes an annotation with alignment, offset, and opacity:

<AnnotationDirective
  content='Target'
  coordinateUnits='Point'
  x='Japan'
  y={75}
  horizontalAlignment='Center'
  verticalAlignment='Middle'
  offset={{ x: 0, y: -10 }}
  opacity={0.85}>
</AnnotationDirective>

See the ChartAnnotationSettingsModel API reference for the full list of properties.

Multiple annotations

Add multiple annotations to the same chart by including more than one AnnotationDirective inside AnnotationsDirective. Each annotation can use its own x, y, region, content, and styling.

<AnnotationsDirective>
  <AnnotationDirective
    content='70 Gold Medals'
    region='Series'
    coordinateUnits='Point'
    x='Japan'
    y={75}>
  </AnnotationDirective>
  <AnnotationDirective
    content='Watermark'
    region='Chart'
    coordinateUnits='Pixel'
    x={20}
    y={20}
    opacity={0.4}>
  </AnnotationDirective>
</AnnotationsDirective>

See Also