Error bullets are special kind of bullets that help illustrate error margin for the particular series value. This tutorial will explain how you can add those to amCharts 4 series.
REQUIRED READING If you’re not familiar how bullets are used in amCharts 4, we suggest you run by “Bullets ” article first.
To create an Error bullet we have a special class ErrorBullet .
It is added to series just like any other regular bullet: by creating (or pushing into) it in its bullets list.
let errorBullet = series . bullets . create (am4charts . ErrorBullet );
errorBullet . isDynamic = true ;
var errorBullet = series . bullets . create ( am4charts . ErrorBullet );
errorBullet . isDynamic = true ;
The purpose of error bullets is to show possible boundaries of value variations. This is why it cannot be just a simple, pixel-sized item.
We need to bind it to an actual scale.
For example, if we have a value 100 with an error margin of 10, we need to show error bullet that spans from 90 to 110.
To do that, we will be using a pixelHeight adapter on a bullet. Our custom function, will modify bullet’s height by accessing relative data points data context and specifically error value.
errorBullet . adapter . add ( " pixelHeight " , function ( pixelHeight , target ) {
let dataItem = target . dataItem ;
let value = dataItem . valueY ;
let errorTopValue = value + dataItem . dataContext . error / 2 ;
let errorTopY = valueAxis . valueToPoint (errorTopValue) . y ;
let errorBottomValue = value - dataItem . dataContext . error / 2 ;
let errorBottomY = valueAxis . valueToPoint (errorBottomValue) . y ;
return Math . abs (errorTopY - errorBottomY);
errorBullet . adapter . add ( " pixelHeight " , function ( pixelHeight , target ) {
var dataItem = target . dataItem ;
var value = dataItem . valueY ;
var errorTopValue = value + dataItem . dataContext . error / 2 ;
var errorTopY = valueAxis . valueToPoint ( errorTopValue ) . y ;
var errorBottomValue = value - dataItem . dataContext . error / 2 ;
var errorBottomY = valueAxis . valueToPoint ( errorBottomValue ) . y ;
return Math . abs ( errorTopY - errorBottomY );
"pixelHeight" : function (pixelHeight , target) {
var dataItem = target.dataItem;
var value = dataItem.valueY;
var errorTopValue = value + dataItem.dataContext.error / 2;
var errorTopY = valueAxis.valueToPoint(errorTopValue).y;
var errorBottomValue = value - dataItem.dataContext.error / 2;
var errorBottomY = valueAxis.valueToPoint(errorBottomValue).y;
return Math.abs(errorTopY - errorBottomY);
IMPORTANT It is important to set isDynamic = true for our bullets. It instructs the chart that this particular bullet is dependent on various factors such as scale changes and should be redrawn, instead of kept at constant size.
Runam4core . useTheme ( am4themes_animated );
var chart = am4core . create ( " chartdiv " , am4charts . XYChart );
chart . padding ( 40 , 40 , 40 , 40 );
var categoryAxis = chart . xAxes . push ( new am4charts . CategoryAxis ());
categoryAxis . renderer . grid . template . location = 0 ;
categoryAxis . dataFields . category = " country " ;
categoryAxis . renderer . minGridDistance = 60 ;
var valueAxis = chart . yAxes . push ( new am4charts . ValueAxis ());
var series = chart . series . push ( new am4charts . LineSeries ());
series . dataFields . categoryX = " country " ;
series . dataFields . valueY = " visits " ;
series . tooltipText = " {valueY.value} error:{error} " ;
var errorBullet = series . bullets . create ( am4charts . ErrorBullet );
errorBullet . isDynamic = true ;
errorBullet . strokeWidth = 2 ;
var circle = errorBullet . createChild ( am4core . Circle );
circle . fill = am4core . color ( " #ffffff " );
// adapter adjusts height of a bullet
errorBullet . adapter . add ( " pixelHeight " , function ( pixelHeight , target ) {
var dataItem = target . dataItem ;
var value = dataItem . valueY ;
var errorTopValue = value + dataItem . dataContext . error / 2 ;
var errorTopY = valueAxis . valueToPoint ( errorTopValue ) . y ;
var errorBottomValue = value - dataItem . dataContext . error / 2 ;
var errorBottomY = valueAxis . valueToPoint ( errorBottomValue ) . y ;
return Math . abs ( errorTopY - errorBottomY );
chart . cursor = new am4charts . XYCursor ();
< div id = " chartdiv " ></ div >
-apple-system , BlinkMacSystemFont, " Segoe UI " , Roboto, Helvetica , Arial , sans-serif ,
" Apple Color Emoji " , " Segoe UI Emoji " , " Segoe UI Symbol " ;
Error Chart error-chart
Since ErrorBullet is like any other Sprite-like element. There’s just one special property for Error bullet: errorLine .
It holds the lines elements that comprise the actual bracket - two threshold lines and one connector line.
If, say, we want to set the width of those lines, we can set strokeWidth property for errorLine.
errorBullet . errorLine . strokeWidth = 2 ;
errorBullet . errorLine . strokeWidth = 2 ;
Making a bullet horizontal is easy: just set rotation = 90 and update its adapter function to use horizontal axis’ scale.
Here’s an example.
Runam4core . useTheme ( am4themes_animated );
var chart = am4core . create ( " chartdiv " , am4charts . XYChart );
chart . padding ( 40 , 40 , 40 , 40 );
var valueAxisX = chart . xAxes . push ( new am4charts . ValueAxis ());
var valueAxisY = chart . yAxes . push ( new am4charts . ValueAxis ());
var series = chart . series . push ( new am4charts . LineSeries ());
series . dataFields . valueX = " x " ;
series . dataFields . valueY = " y " ;
series . strokeOpacity = 0 ;
var errorBulletY = series . bullets . create ( am4charts . ErrorBullet );
errorBulletY . isDynamic = true ;
errorBulletY . strokeWidth = 2 ;
errorBulletY . tooltipText = " x: {valueX.value} y: {valueY.value} error x:{errorX}, error y:{errorY} " ;
// adapter adjusts height of a bullet
errorBulletY . adapter . add ( " pixelHeight " , function ( pixelHeight , target ) {
var dataItem = target . dataItem ;
var value = dataItem . valueY ;
var errorTopValue = value + dataItem . dataContext . errorY / 2 ;
var errorTopY = valueAxisY . valueToPoint ( errorTopValue ) . y ;
var errorBottomValue = value - dataItem . dataContext . errorY / 2 ;
var errorBottomY = valueAxisY . valueToPoint ( errorBottomValue ) . y ;
return Math . abs ( errorTopY - errorBottomY );
var errorBulletX = series . bullets . create ( am4charts . ErrorBullet );
errorBulletX . tooltipText = " x: {valueX.value} y: {valueY.value} error x:{errorX}, error y:{errorY} " ;
errorBulletX . isDynamic = true ;
errorBulletX . strokeWidth = 2 ;
errorBulletX . rotation = 90 ; // need to rotate, as error bullet is vertical
var circle = errorBulletX . createChild ( am4core . Circle );
circle . fill = am4core . color ( " #ffffff " );
// adapter adjusts height of a bullet
errorBulletX . adapter . add ( " pixelHeight " , function ( pixelHeight , target ) {
var dataItem = target . dataItem ;
var value = dataItem . valueY ;
var errorTopValue = value + dataItem . dataContext . errorX / 2 ;
var errorTopX = valueAxisX . valueToPoint ( errorTopValue ) . x ;
var errorBottomValue = value - dataItem . dataContext . errorX / 2 ;
var errorBottomX = valueAxisX . valueToPoint ( errorBottomValue ) . x ;
return Math . abs ( errorTopX - errorBottomX );
chart . cursor = new am4charts . XYCursor ();
chart . cursor . behavior = " zoomXY " ;
chart . scrollbarX = new am4core . Scrollbar ();
chart . scrollbarY = new am4core . Scrollbar ();
< div id = " chartdiv " ></ div >
-apple-system , BlinkMacSystemFont, " Segoe UI " , Roboto, Helvetica , Arial , sans-serif ,
" Apple Color Emoji " , " Segoe UI Emoji " , " Segoe UI Symbol " ;
XY Error Chart xy-error-chart
Here’s another example which uses modified data and code for bullet sizing, to display asymmetric bullets.
Run//am4core.useTheme(am4themes_animated);
var chart = am4core . create ( " chartdiv " , am4charts . XYChart );
chart . padding ( 40 , 40 , 40 , 40 );
var categoryAxis = chart . xAxes . push ( new am4charts . CategoryAxis ());
categoryAxis . renderer . grid . template . location = 0 ;
categoryAxis . dataFields . category = " country " ;
categoryAxis . renderer . minGridDistance = 60 ;
var valueAxis = chart . yAxes . push ( new am4charts . ValueAxis ());
var series = chart . series . push ( new am4charts . LineSeries ());
series . dataFields . categoryX = " country " ;
series . dataFields . valueY = " visits " ;
series . tooltipText = " {valueY.value} error: {error1} - {error2} " ;
var errorBullet = series . bullets . create ( am4charts . ErrorBullet );
errorBullet . isDynamic = true ;
errorBullet . strokeWidth = 2 ;
//errorBullet.verticalCenter = "top";
// adapter adjusts height of a bullet
errorBullet . adapter . add ( " pixelHeight " , function ( pixelHeight , target ) {
var dataItem = target . dataItem ;
var value = dataItem . valueY ;
var errorTopValue = value + dataItem . dataContext . error1 ;
var errorTopY = valueAxis . valueToPoint ( errorTopValue ) . y ;
var errorBottomValue = value - dataItem . dataContext . error2 ;
var errorBottomY = valueAxis . valueToPoint ( errorBottomValue ) . y ;
return Math . abs ( errorTopY - errorBottomY );
errorBullet . adapter . add ( " dy " , function ( dy , target ) {
var dataItem = target . dataItem ;
var value = dataItem . valueY ;
var errorTopValue = value + dataItem . dataContext . error1 ;
var errorTopY = valueAxis . valueToPoint ( errorTopValue ) . y ;
var errorBottomValue = value - dataItem . dataContext . error2 ;
var errorBottomY = valueAxis . valueToPoint ( errorBottomValue ) . y ;
var errorCenterY = valueAxis . valueToPoint ( value ) . y ;
return ( errorTopY - errorCenterY ) / 2 - ( errorCenterY - errorBottomY ) / 2 ;
chart . cursor = new am4charts . XYCursor ();
< div id = " chartdiv " ></ div >
-apple-system , BlinkMacSystemFont, " Segoe UI " , Roboto, Helvetica , Arial , sans-serif ,
" Apple Color Emoji " , " Segoe UI Emoji " , " Segoe UI Symbol " ;
Asymmetric Error Chart asymmetric-error-chart