A line chart that turns orange where it drops below zero, line and fill alike. The same trick works for any threshold, not just zero.
Coloring the part of a line beyond a threshold shows at a glance when a value was good or bad, without reading the axis. Zero is the natural line for profit and loss or temperatures; a target, a limit or an average works the same way.
Built with amCharts 5, a JavaScript library. The JavaScript includes your theme and renderer (canvas or SVG); the JSON also follows the changes you make with the controls.
npm install @amcharts/amcharts5. See Getting started.
The same chart as a JSON config. Chart Maker reads and writes this format, the library's JSON parser turns it into a chart, and the <am5-chart> element puts it on a page with no code."type" is the class to create and "settings" what you would pass to its new() in code; "properties" fill in its parts, lists such as series and axes or templates such as columns.template; "refs" holds objects used in more than one place ("#series-0" stands for the one named series-0); a string starting with "@" takes a value from another object, such as "@series.get('fill')".
A complete page. Save it as an .html file and open it in a browser.
Paste this into an AI coding assistant to build the chart from scratch. More in amCharts & AI.
// Create root and chart
var root = am5.Root.new("chartdiv");
root.setThemes([am5themes_Animated.new(root), am5themes_Responsive.new(root)]);
var chart = root.container.children.push(
am5xy.XYChart.new(root, {
wheelY: "zoomX" // the mouse wheel zooms in on the dates
})
);
// Generate random data: a slow wave with some noise on it,
// so the line dips below zero and comes back up
var data = generateChartData();
function generateChartData() {
var chartData = [];
var firstDate = new Date();
firstDate.setDate(firstDate.getDate() - 150);
var noise = 0;
for (var i = 0; i < 150; i++) {
var newDate = new Date(firstDate);
newDate.setHours(0, 0, 0);
newDate.setDate(newDate.getDate() + i);
// random noise that wanders but keeps pulling back toward zero
noise = (noise + (Math.random() - 0.5) * 8) * 0.92;
chartData.push({
date: newDate.getTime(),
value: Math.round(Math.sin((i + 8) / 20) * 45 + 10 + noise) // a slow sine wave plus the noise
});
}
return chartData;
}
// Create Y-axis
var yAxis = chart.yAxes.push(
am5xy.ValueAxis.new(root, {
// the axis tooltip shows one more decimal than the axis labels
extraTooltipPrecision: 1,
renderer: am5xy.AxisRendererY.new(root, {
minGridDistance: 30 // at least 30px between labels
})
})
);
// Create X-Axis
var xAxis = chart.xAxes.push(
am5xy.DateAxis.new(root, {
baseInterval: { timeUnit: "day", count: 1 }, // one point per day
renderer: am5xy.AxisRendererX.new(root, {
minorGridEnabled: true, // fainter grid lines between the labeled dates
cellStartLocation: 0.2,
cellEndLocation: 0.8
})
})
);
// Create series
var series = chart.series.push(
am5xy.SmoothedXLineSeries.new(root, {
xAxis: xAxis,
yAxis: yAxis,
valueYField: "value",
valueXField: "date",
tooltip: am5.Tooltip.new(root, {
labelText:"{valueX.formatDate()}: {valueY}", // the date and the value
pointerOrientation:"horizontal" // the tooltip points sideways at the line
})
})
);
series.strokes.template.setAll({
strokeWidth: 3 // a 3px line
});
series.fills.template.setAll({
fillOpacity: 0.5, // a half-transparent fill...
visible: true // ...which line series hide by default
});
series.data.setAll(data);
// Color the part below zero: a series axis range from far below the data up to 0
// draws that stretch of the line and fill in its own color
// https://www.amcharts.com/docs/v5/charts/xy-chart/axes/axis-ranges/#series-axis-ranges
var rangeDataItem = yAxis.makeDataItem({
value: -1000,
endValue: 0
});
var range = series.createAxisRange(rangeDataItem);
range.strokes.template.setAll({
stroke: am5.color(0xff621f), // orange below zero...
strokeWidth: 3 // ...as thick as the main line
});
range.fills.template.setAll({
fill: am5.color(0xff621f), // and an orange fill
fillOpacity: 0.5,
visible: true // line fills are hidden by default
});
// Add cursor
chart.set(
"cursor",
am5xy.XYCursor.new(root, {
// drag across the plot to zoom into those days
behavior: "zoomX",
xAxis: xAxis // the cursor snaps to whole days
})
);
xAxis.set( // the cursor shows the date on this axis...
"tooltip",
am5.Tooltip.new(root, {})
);
yAxis.set( // ...and the value on this one
"tooltip",
am5.Tooltip.new(root, {})
);
// Add scrollbar, hidden at first
// https://www.amcharts.com/docs/v5/charts/xy-chart/scrollbars/
chart.set("scrollbarX", am5.Scrollbar.new(root, { orientation: "horizontal", forceHidden: true }));
// Make stuff animate on load
// https://www.amcharts.com/docs/v5/concepts/animations/
series.appear(1000);
chart.appear(1000, 100);
{
"type": "XYChart",
"settings": {
"wheelY": "zoomX",
"cursor": {
"type": "XYCursor",
"settings": {
"behavior": "zoomX",
"xAxis": "#axis-0"
}
},
"scrollbarX": {
"type": "Scrollbar",
"settings": {
"orientation": "horizontal",
"forceHidden": true
}
}
},
"properties": {
"series": [
"#series-0"
],
"xAxes": [
"#axis-0"
],
"yAxes": [
"#axis-1"
]
},
"refs": [
{
"data-0": [
{
"date": 1778446800607,
"value": 31
},
{
"date": 1778533200607,
"value": 32
},
{
"date": 1778619600607,
"value": 31
},
{
"date": 1778706000607,
"value": 29
},
{
"date": 1778792400607,
"value": 34
},
{
"date": 1778878800607,
"value": 37
},
{
"date": 1778965200607,
"value": 36
},
{
"date": 1779051600607,
"value": 39
},
{
"date": 1779138000607,
"value": 43
},
{
"date": 1779224400607,
"value": 44
},
{
"date": 1779310800607,
"value": 49
},
{
"date": 1779397200607,
"value": 50
},
{
"date": 1779483600607,
"value": 49
},
{
"date": 1779570000607,
"value": 48
},
{
"date": 1779656400607,
"value": 46
},
{
"date": 1779742800607,
"value": 49
},
{
"date": 1779829200607,
"value": 47
},
{
"date": 1779915600607,
"value": 51
},
{
"date": 1780002000607,
"value": 50
},
{
"date": 1780088400607,
"value": 54
},
{
"date": 1780174800607,
"value": 56
},
{
"date": 1780261200607,
"value": 53
},
{
"date": 1780347600607,
"value": 50
},
{
"date": 1780434000607,
"value": 47
},
{
"date": 1780520400607,
"value": 50
},
{
"date": 1780606800607,
"value": 50
},
{
"date": 1780693200607,
"value": 50
},
{
"date": 1780779600607,
"value": 50
},
{
"date": 1780866000607,
"value": 47
},
{
"date": 1780952400607,
"value": 50
},
{
"date": 1781038800607,
"value": 47
},
{
"date": 1781125200607,
"value": 46
},
{
"date": 1781211600607,
"value": 46
},
{
"date": 1781298000607,
"value": 48
},
{
"date": 1781384400607,
"value": 47
},
{
"date": 1781470800607,
"value": 47
},
{
"date": 1781557200607,
"value": 43
},
{
"date": 1781643600607,
"value": 41
},
{
"date": 1781730000607,
"value": 43
},
{
"date": 1781816400607,
"value": 41
},
{
"date": 1781902800607,
"value": 37
},
{
"date": 1781989200607,
"value": 32
},
{
"date": 1782075600607,
"value": 33
},
{
"date": 1782162000607,
"value": 33
},
{
"date": 1782248400607,
"value": 33
},
{
"date": 1782334800607,
"value": 30
},
{
"date": 1782421200607,
"value": 29
},
{
"date": 1782507600607,
"value": 26
},
{
"date": 1782594000607,
"value": 27
},
{
"date": 1782680400607,
"value": 21
},
{
"date": 1782766800607,
"value": 17
},
{
"date": 1782853200607,
"value": 13
},
{
"date": 1782939600607,
"value": 14
},
{
"date": 1783026000607,
"value": 15
},
{
"date": 1783112400607,
"value": 12
},
{
"date": 1783198800607,
"value": 8
},
{
"date": 1783285200607,
"value": 3
},
{
"date": 1783371600607,
"value": 2
},
{
"date": 1783458000607,
"value": 2
},
{
"date": 1783544400607,
"value": 2
},
{
"date": 1783630800607,
"value": 1
},
{
"date": 1783717200607,
"value": 0
},
{
"date": 1783803600607,
"value": -2
},
{
"date": 1783890000607,
"value": -4
},
{
"date": 1783976400607,
"value": -5
},
{
"date": 1784062800607,
"value": -8
},
{
"date": 1784149200607,
"value": -7
},
{
"date": 1784235600607,
"value": -6
},
{
"date": 1784322000607,
"value": -9
},
{
"date": 1784408400607,
"value": -8
},
{
"date": 1784494800607,
"value": -13
},
{
"date": 1784581200607,
"value": -18
},
{
"date": 1784667600607,
"value": -23
},
{
"date": 1784754000607,
"value": -25
},
{
"date": 1784840400607,
"value": -23
},
{
"date": 1784926800607,
"value": -23
},
{
"date": 1785013200607,
"value": -25
},
{
"date": 1785099600607,
"value": -24
},
{
"date": 1785186000607,
"value": -29
},
{
"date": 1785272400607,
"value": -28
},
{
"date": 1785358800607,
"value": -32
},
{
"date": 1785445200607,
"value": -34
},
{
"date": 1785531600607,
"value": -32
},
{
"date": 1785618000607,
"value": -33
},
{
"date": 1785704400607,
"value": -30
},
{
"date": 1785790800607,
"value": -30
},
{
"date": 1785877200607,
"value": -27
},
{
"date": 1785963600607,
"value": -27
},
{
"date": 1786050000607,
"value": -25
},
{
"date": 1786136400607,
"value": -23
},
{
"date": 1786222800607,
"value": -20
},
{
"date": 1786309200607,
"value": -18
},
{
"date": 1786395600607,
"value": -18
},
{
"date": 1786482000607,
"value": -18
},
{
"date": 1786568400607,
"value": -17
},
{
"date": 1786654800607,
"value": -19
},
{
"date": 1786741200607,
"value": -21
},
{
"date": 1786827600607,
"value": -23
},
{
"date": 1786914000607,
"value": -19
},
{
"date": 1787000400607,
"value": -16
},
{
"date": 1787086800607,
"value": -15
},
{
"date": 1787173200607,
"value": -17
},
{
"date": 1787259600607,
"value": -18
},
{
"date": 1787346000607,
"value": -15
},
{
"date": 1787432400607,
"value": -11
},
{
"date": 1787518800607,
"value": -9
},
{
"date": 1787605200607,
"value": -8
},
{
"date": 1787691600607,
"value": -8
},
{
"date": 1787778000607,
"value": -6
},
{
"date": 1787864400607,
"value": -7
},
{
"date": 1787950800607,
"value": -4
},
{
"date": 1788037200607,
"value": -3
},
{
"date": 1788123600607,
"value": 2
},
{
"date": 1788210000607,
"value": 6
},
{
"date": 1788296400607,
"value": 5
},
{
"date": 1788382800607,
"value": 10
},
{
"date": 1788469200607,
"value": 12
},
{
"date": 1788555600607,
"value": 13
},
{
"date": 1788642000607,
"value": 13
},
{
"date": 1788728400607,
"value": 14
},
{
"date": 1788814800607,
"value": 15
},
{
"date": 1788901200607,
"value": 17
},
{
"date": 1788987600607,
"value": 18
},
{
"date": 1789074000607,
"value": 22
},
{
"date": 1789160400607,
"value": 23
},
{
"date": 1789246800607,
"value": 25
},
{
"date": 1789333200607,
"value": 28
},
{
"date": 1789419600607,
"value": 29
},
{
"date": 1789506000607,
"value": 29
},
{
"date": 1789592400607,
"value": 31
},
{
"date": 1789678800607,
"value": 30
},
{
"date": 1789765200607,
"value": 30
},
{
"date": 1789851600607,
"value": 35
},
{
"date": 1789938000607,
"value": 34
},
{
"date": 1790024400607,
"value": 36
},
{
"date": 1790110800607,
"value": 41
},
{
"date": 1790197200607,
"value": 45
},
{
"date": 1790283600607,
"value": 49
},
{
"date": 1790370000607,
"value": 53
},
{
"date": 1790456400607,
"value": 54
},
{
"date": 1790542800607,
"value": 57
},
{
"date": 1790629200607,
"value": 61
},
{
"date": 1790715600607,
"value": 60
},
{
"date": 1790802000607,
"value": 57
},
{
"date": 1790888400607,
"value": 55
},
{
"date": 1790974800607,
"value": 58
},
{
"date": 1791061200607,
"value": 60
},
{
"date": 1791147600607,
"value": 64
},
{
"date": 1791234000607,
"value": 64
},
{
"date": 1791320400607,
"value": 60
}
]
},
{
"axis-0": {
"type": "DateAxis",
"settings": {
"baseInterval": {
"timeUnit": "day",
"count": 1
},
"renderer": {
"type": "AxisRendererX",
"settings": {
"minorGridEnabled": true,
"cellStartLocation": 0.2,
"cellEndLocation": 0.8
}
},
"tooltip": {
"type": "Tooltip"
}
}
}
},
{
"axis-1": {
"type": "ValueAxis",
"settings": {
"extraTooltipPrecision": 1,
"renderer": {
"type": "AxisRendererY",
"settings": {
"minGridDistance": 30
}
},
"tooltip": {
"type": "Tooltip"
}
}
}
},
{
"series-0": {
"type": "SmoothedXLineSeries",
"settings": {
"xAxis": "#axis-0",
"yAxis": "#axis-1",
"valueYField": "value",
"valueXField": "date",
"tooltip": {
"type": "Tooltip",
"settings": {
"labelText": "{valueX.formatDate()}: {valueY}",
"pointerOrientation": "horizontal"
}
}
},
"properties": {
"data": "#data-0",
"strokes": {
"properties": {
"template": {
"settings": {
"strokeWidth": 3
}
}
}
},
"fills": {
"properties": {
"template": {
"settings": {
"fillOpacity": 0.5,
"visible": true
}
}
}
}
}
}
},
{
"seriesAxisRange-0": {
"axis": "#axis-1",
"series": "#series-0",
"settings": {
"value": -1000,
"endValue": 0
},
"__parseLogic": "axisRange",
"fills": {
"fill": {
"type": "Color",
"value": "#ff621f"
},
"fillOpacity": 0.5,
"visible": true
},
"strokes": {
"stroke": {
"type": "Color",
"value": "#ff621f"
},
"strokeWidth": 3
}
}
}
]
}