Line with Different Negative Color
A line chart that turns red where it drops below zero, line and fill alike. The same trick works for any threshold, not just zero.
About this chart
When to color by threshold
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.
Good for
- Profit and loss, gains and losses
- Temperatures above and below freezing
- Values against a target or a safe limit
Think twice when
- Several thresholds at once: bands of color get hard to read
- Data that hovers around the threshold: the color flickers
- Readers who can’t tell the colors apart: label the threshold too
For developers
Get the code.
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.
For projects that use npm:
How it reads:
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.How it reads:
"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://docs.amcharts.com/v5/charts/xy-chart/axes/axis-ranges/#series-axis-ranges
var rangeDataItem = yAxis.makeDataItem({
value: -1000,
endValue: 0
});
var range = series.createAxisRange(rangeDataItem);
// below zero in the theme's color for negative values (red by default), so it suits every theme and dark mode
var negativeColor = root.interfaceColors.get("negative");
range.strokes.template.setAll({
stroke: negativeColor, // that color below zero...
strokeWidth: 3 // ...as thick as the main line
});
range.fills.template.setAll({
fill: negativeColor, // and a fill in it
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://docs.amcharts.com/v5/charts/xy-chart/scrollbars/
chart.set("scrollbarX", am5.Scrollbar.new(root, { orientation: "horizontal", forceHidden: true }));
// Make stuff animate on load
// https://docs.amcharts.com/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": 1778965200343,
"value": 29
},
{
"date": 1779051600343,
"value": 31
},
{
"date": 1779138000343,
"value": 35
},
{
"date": 1779224400343,
"value": 40
},
{
"date": 1779310800343,
"value": 43
},
{
"date": 1779397200343,
"value": 47
},
{
"date": 1779483600343,
"value": 44
},
{
"date": 1779570000343,
"value": 49
},
{
"date": 1779656400343,
"value": 52
},
{
"date": 1779742800343,
"value": 50
},
{
"date": 1779829200343,
"value": 50
},
{
"date": 1779915600343,
"value": 54
},
{
"date": 1780002000343,
"value": 57
},
{
"date": 1780088400343,
"value": 59
},
{
"date": 1780174800343,
"value": 58
},
{
"date": 1780261200343,
"value": 59
},
{
"date": 1780347600343,
"value": 58
},
{
"date": 1780434000343,
"value": 62
},
{
"date": 1780520400343,
"value": 64
},
{
"date": 1780606800343,
"value": 66
},
{
"date": 1780693200343,
"value": 64
},
{
"date": 1780779600343,
"value": 66
},
{
"date": 1780866000343,
"value": 68
},
{
"date": 1780952400343,
"value": 70
},
{
"date": 1781038800343,
"value": 71
},
{
"date": 1781125200343,
"value": 71
},
{
"date": 1781211600343,
"value": 72
},
{
"date": 1781298000343,
"value": 71
},
{
"date": 1781384400343,
"value": 66
},
{
"date": 1781470800343,
"value": 67
},
{
"date": 1781557200343,
"value": 67
},
{
"date": 1781643600343,
"value": 66
},
{
"date": 1781730000343,
"value": 61
},
{
"date": 1781816400343,
"value": 56
},
{
"date": 1781902800343,
"value": 52
},
{
"date": 1781989200343,
"value": 49
},
{
"date": 1782075600343,
"value": 48
},
{
"date": 1782162000343,
"value": 45
},
{
"date": 1782248400343,
"value": 41
},
{
"date": 1782334800343,
"value": 40
},
{
"date": 1782421200343,
"value": 41
},
{
"date": 1782507600343,
"value": 38
},
{
"date": 1782594000343,
"value": 34
},
{
"date": 1782680400343,
"value": 36
},
{
"date": 1782766800343,
"value": 36
},
{
"date": 1782853200343,
"value": 32
},
{
"date": 1782939600343,
"value": 31
},
{
"date": 1783026000343,
"value": 29
},
{
"date": 1783112400343,
"value": 27
},
{
"date": 1783198800343,
"value": 25
},
{
"date": 1783285200343,
"value": 21
},
{
"date": 1783371600343,
"value": 15
},
{
"date": 1783458000343,
"value": 16
},
{
"date": 1783544400343,
"value": 15
},
{
"date": 1783630800343,
"value": 13
},
{
"date": 1783717200343,
"value": 9
},
{
"date": 1783803600343,
"value": 9
},
{
"date": 1783890000343,
"value": 4
},
{
"date": 1783976400343,
"value": 2
},
{
"date": 1784062800343,
"value": -1
},
{
"date": 1784149200343,
"value": -2
},
{
"date": 1784235600343,
"value": -6
},
{
"date": 1784322000343,
"value": -5
},
{
"date": 1784408400343,
"value": -11
},
{
"date": 1784494800343,
"value": -10
},
{
"date": 1784581200343,
"value": -10
},
{
"date": 1784667600343,
"value": -12
},
{
"date": 1784754000343,
"value": -14
},
{
"date": 1784840400343,
"value": -14
},
{
"date": 1784926800343,
"value": -14
},
{
"date": 1785013200343,
"value": -15
},
{
"date": 1785099600343,
"value": -19
},
{
"date": 1785186000343,
"value": -20
},
{
"date": 1785272400343,
"value": -25
},
{
"date": 1785358800343,
"value": -29
},
{
"date": 1785445200343,
"value": -32
},
{
"date": 1785531600343,
"value": -30
},
{
"date": 1785618000343,
"value": -31
},
{
"date": 1785704400343,
"value": -33
},
{
"date": 1785790800343,
"value": -34
},
{
"date": 1785877200343,
"value": -35
},
{
"date": 1785963600343,
"value": -36
},
{
"date": 1786050000343,
"value": -34
},
{
"date": 1786136400343,
"value": -38
},
{
"date": 1786222800343,
"value": -36
},
{
"date": 1786309200343,
"value": -37
},
{
"date": 1786395600343,
"value": -39
},
{
"date": 1786482000343,
"value": -39
},
{
"date": 1786568400343,
"value": -41
},
{
"date": 1786654800343,
"value": -43
},
{
"date": 1786741200343,
"value": -43
},
{
"date": 1786827600343,
"value": -40
},
{
"date": 1786914000343,
"value": -39
},
{
"date": 1787000400343,
"value": -36
},
{
"date": 1787086800343,
"value": -32
},
{
"date": 1787173200343,
"value": -33
},
{
"date": 1787259600343,
"value": -32
},
{
"date": 1787346000343,
"value": -34
},
{
"date": 1787432400343,
"value": -31
},
{
"date": 1787518800343,
"value": -26
},
{
"date": 1787605200343,
"value": -28
},
{
"date": 1787691600343,
"value": -26
},
{
"date": 1787778000343,
"value": -28
},
{
"date": 1787864400343,
"value": -29
},
{
"date": 1787950800343,
"value": -26
},
{
"date": 1788037200343,
"value": -22
},
{
"date": 1788123600343,
"value": -17
},
{
"date": 1788210000343,
"value": -14
},
{
"date": 1788296400343,
"value": -10
},
{
"date": 1788382800343,
"value": -11
},
{
"date": 1788469200343,
"value": -10
},
{
"date": 1788555600343,
"value": -8
},
{
"date": 1788642000343,
"value": -5
},
{
"date": 1788728400343,
"value": 1
},
{
"date": 1788814800343,
"value": 1
},
{
"date": 1788901200343,
"value": 5
},
{
"date": 1788987600343,
"value": 10
},
{
"date": 1789074000343,
"value": 13
},
{
"date": 1789160400343,
"value": 14
},
{
"date": 1789246800343,
"value": 19
},
{
"date": 1789333200343,
"value": 19
},
{
"date": 1789419600343,
"value": 22
},
{
"date": 1789506000343,
"value": 26
},
{
"date": 1789592400343,
"value": 27
},
{
"date": 1789678800343,
"value": 29
},
{
"date": 1789765200343,
"value": 33
},
{
"date": 1789851600343,
"value": 35
},
{
"date": 1789938000343,
"value": 35
},
{
"date": 1790024400343,
"value": 35
},
{
"date": 1790110800343,
"value": 35
},
{
"date": 1790197200343,
"value": 33
},
{
"date": 1790283600343,
"value": 32
},
{
"date": 1790370000343,
"value": 32
},
{
"date": 1790456400343,
"value": 31
},
{
"date": 1790542800343,
"value": 36
},
{
"date": 1790629200343,
"value": 35
},
{
"date": 1790715600343,
"value": 34
},
{
"date": 1790802000343,
"value": 39
},
{
"date": 1790888400343,
"value": 44
},
{
"date": 1790974800343,
"value": 44
},
{
"date": 1791061200343,
"value": 42
},
{
"date": 1791147600343,
"value": 40
},
{
"date": 1791234000343,
"value": 43
},
{
"date": 1791320400343,
"value": 48
},
{
"date": 1791406800343,
"value": 52
},
{
"date": 1791493200343,
"value": 56
},
{
"date": 1791579600343,
"value": 53
},
{
"date": 1791666000343,
"value": 53
},
{
"date": 1791752400343,
"value": 52
},
{
"date": 1791838800343,
"value": 49
}
]
},
{
"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": "@root.interfaceColors.get('negative')",
"fillOpacity": 0.5,
"visible": true
},
"strokes": {
"stroke": "@root.interfaceColors.get('negative')",
"strokeWidth": 3
}
}
}
]
}



