Forest Plot
This demo shows a basic Forest Plot chart.
This relatively simple demo utilizes a bunch of amCharts 5 concepts: template fields, heat rules, axis ranges, and adapters.
Related tutorials
- Axis ranges (used to display vertical comparison guide)
- Heat rules (used to size bullets based on their value)
- Adapters (used to dynamically update content of axis labels)
- Template fields (used to override bullet settings via data)
Demo source
<!-- Styles -->
<style>
#chartdiv {
width: 100%;
height: 500px;
}
</style>
<!-- Resources -->
<script src="https://cdn.amcharts.com/lib/5/index.js"></script>
<script src="https://cdn.amcharts.com/lib/5/xy.js"></script>
<script src="https://cdn.amcharts.com/lib/5/themes/Animated.js"></script>
<!-- Chart code -->
<script>
am5.ready(function() {
// Create root element
// https://www.amcharts.com/docs/v5/getting-started/#Root_element
var root = am5.Root.new("chartdiv");
// Set themes
// https://www.amcharts.com/docs/v5/concepts/themes/
root.setThemes([
am5themes_Animated.new(root)
]);
// Create chart
// https://www.amcharts.com/docs/v5/charts/xy-chart/
var chart = root.container.children.push(am5xy.XYChart.new(root, {
panX: false,
panY: false,
wheelX: "panX",
wheelY: "zoomX",
layout: root.verticalLayout
}));
// Data
var data = [{
category: "Smith et al. 1991",
measure: 1.3,
bulletSize: 25,
high: 3.4,
low: 1.0
}, {
category: "Jones et al. 1993",
measure: 2.1,
bulletSize: 15,
high: 2.6,
low: 0.5
}, {
category: "Smith et al. 1999",
measure: 1.8,
bulletSize: 10,
high: 3.2,
low: 0.9
}, {
category: "Ng et al. 2004",
measure: 2.3,
bulletSize: 30,
high: 2.7,
low: 1.9
}, {
category: "Chu et al. 2009",
measure: 2.1,
bulletSize: 35,
high: 2.5,
low: 1.8
}, {
category: "Summary measure",
measure: 2.2,
bulletSize: 55,
high: 2.4,
low: 1.9,
bulletSettings: {
rotation: 45,
fill: am5.color(0xffffff)
},
textSettings: {
text: "{valueX}"
}
}];
// Create axes
// https://www.amcharts.com/docs/v5/charts/xy-chart/axes/
var yRenderer = am5xy.AxisRendererY.new(root, {
inversed: true,
minorGridEnabled: true
});
var yAxis = chart.yAxes.push(am5xy.CategoryAxis.new(root, {
categoryField: "category",
renderer: yRenderer
}));
yAxis.data.setAll(data);
var yRenderer2 = am5xy.AxisRendererY.new(root, {
opposite: true,
inversed: true
})
var yAxis2 = chart.yAxes.push(am5xy.CategoryAxis.new(root, {
categoryField: "category",
renderer: yRenderer2
}));
yRenderer2.grid.template.setAll({
forceHidden: true
})
yRenderer2.labels.template.setAll({
populateText: true
})
yRenderer2.labels.template.adapters.add("text", function(text, target) {
return "[bold]{measure}[/] ({low}-{high})";
})
yAxis2.data.setAll(data);
var xAxis = chart.xAxes.push(am5xy.ValueAxis.new(root, {
renderer: am5xy.AxisRendererX.new(root, {
strokeOpacity: 0.1
})
}));
// Add series
// https://www.amcharts.com/docs/v5/charts/xy-chart/series/
// Column/line series
var series = chart.series.push(am5xy.ColumnSeries.new(root, {
xAxis: xAxis,
yAxis: yAxis,
valueXField: "high",
openValueXField: "low",
categoryYField: "category"
}));
series.columns.template.setAll({
height: 1,
strokeWidth: 1
});
series.data.setAll(data);
// Series for bullets
var series2 = chart.series.push(am5xy.LineSeries.new(root, {
xAxis: xAxis,
yAxis: yAxis,
valueXField: "measure",
categoryYField: "category",
valueField: "bulletSize",
calculateAggregates: true,
fill: series.get("fill"),
tooltip: am5.Tooltip.new(root, {
labelText: "[bold]{valueX}[/] ({low}-{high})"
})
}));
series2.strokes.template.setAll({
forceHidden: true
});
var rectangleTemplate = am5.Template.new({
stroke: series.get("fill"),
fill: series.get("fill"),
centerY: am5.p50,
centerX: am5.p50,
strokeWidth: 2,
templateField: "bulletSettings"
});
series2.bullets.push(function() {
return am5.Bullet.new(root, {
sprite: am5.Rectangle.new(root, {}, rectangleTemplate)
});
});
series2.set("heatRules", [{
target: rectangleTemplate,
key: "width",
min: 10,
max: 40,
dataField: "value"
}, {
target: rectangleTemplate,
key: "height",
min: 10,
max: 40,
dataField: "value"
}]);
series2.bullets.push(function() {
return am5.Bullet.new(root, {
sprite: am5.Label.new(root, {
centerX: am5.p50,
centerY: am5.p50,
templateField: "textSettings",
populateText: true
})
});
});
series2.data.setAll(data);
// Create a summary line
var rangeDataItem = xAxis.makeDataItem({
value: 2.2
});
var range = xAxis.createAxisRange(rangeDataItem);
rangeDataItem.get("grid").setAll({
stroke: am5.color(0x000000),
strokeOpacity: 0.3,
strokeDasharray: [3, 3]
});
// Add cursor
// https://www.amcharts.com/docs/v5/charts/xy-chart/cursor/
var cursor = chart.set("cursor", am5xy.XYCursor.new(root, {
xAxis: xAxis
}));
cursor.lineY.set("visible", false);
cursor.lineX.set("visible", false);
// Make stuff animate on load
// https://www.amcharts.com/docs/v5/concepts/animations/
series.appear();
series2.appear();
chart.appear(1000, 100);
}); // end am5.ready()
</script>
<!-- HTML -->
<div id="chartdiv"></div>