Related
I am using a combination of stack bar and line chart at the same with the help of HighChart, I want to be able to select a bar(or in my case the entire stack bar as well as the point in the line graph) and change its color when I click on it,
Right now I am able to select a bar and change its color but not able to change the color of both bars and the point of the line which was clicked
Below is the click of the code which I tried from my end, I want to be able to select the entire bar and line when clicked, but I am only able to select one of them
SandBox Link
I tried this sorry that the sandbox link was broken
Highcharts.chart('container', {
"chart": {
"zoomType": "xy",
"height": 320
},
"credits": {
"enabled": false
},
"title": {
"text": "",
"align": "left",
"style": {
"fontFamily": "Poppins, Helvetica, \"sans-serif\"",
"fontWeight": "600"
}
},
"xAxis": {
"title": {
"text": ""
},
"categories": [
"0.01-0.05",
"0.06-0.10",
"0.11-0.15",
"0.16-0.20",
"0.21-0.25",
"0.26-0.30",
"0.31-0.35",
"0.36-0.40",
"0.41-0.45",
"0.46-0.50",
"0.51-0.55",
"0.56-0.60",
"0.61-0.65",
"0.66-0.70",
"0.71-0.75",
"0.76-0.80",
"0.81-0.85",
"0.86-0.90",
"0.91-0.95",
"0.96-1.00"
],
"crosshair": true,
"plotLines": [{
"color": "#A9A9A9",
"width": 3,
"value": 9.5,
"dashStyle": "longdashdot"
}]
},
"yAxis": [{
"title": {
"text": "Count"
},
"min": 0
},
{
"title": {
"text": "y1 count"
},
"opposite": true,
"min": 0
}
],
"tooltip": {
"shared": true
},
plotOptions: {
series: {
stacking: 'normal',
point: {
events: {
click() {
var indexP = this.x,
series = this.series.chart.series;
if (series[0].data[indexP].selected) {
//unselect
series[0].data[indexP].select(false, true);
series[1].data[indexP].select(false, true);
} else {
var i = 0;
var len = series[1].data.length;
for (i = 0; i < len; i++) { //clear all selection
series[0].data[i].select(false, true);
series[1].data[i].select(false, true);
series[2].data[i].select(false, true);
}
//select
series[0].data[indexP].select(true, true);
series[1].data[indexP].select(true, true);
series[2].data[indexP].select(true, true);
}
return false;
}
}
}
}
},
"legend": {
"layout": "horizontal",
"align": "right",
"verticalAlign": "top"
},
"exporting": {
"enabled": false
},
"series": [{
"name": "y1",
"type": "column",
"stack": 1,
"yAxis": 1,
"color": "rgb(217, 141, 39)",
"data": [
1,
13,
24,
25,
34,
74,
104,
66,
104,
121,
111,
89,
87,
97,
93,
92,
100,
147,
250,
567
],
"tooltip": {
"valueSuffix": " "
}
},
{
"name": "y3",
"type": "column",
"stack": 1,
"yAxis": 1,
"color": "rgb(44, 99, 143)",
"data": [
463,
287,
208,
201,
209,
197,
171,
150,
134,
102,
65,
50,
36,
24,
33,
20,
13,
13,
10,
9
],
"tooltip": {
"valueSuffix": ""
}
},
{
"name": "y3",
"type": "line",
"color": "#F1416C",
"data": [
1,
14,
38,
63,
97,
171,
275,
341,
445,
566,
677,
766,
853,
950,
1043,
1135,
1235,
1382,
1632,
2199
],
"tooltip": {
"valueSuffix": " "
}
}
]
})
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>
<div id="container"></div>
Wanting to use ChartJS to generate a complex combination graph. All working well with the exception of being able to control the formatting of the legend.
Trying to achieve something like this:
desired chart display
The code I have for this is below. Have tried using the generateLabels function to override but with no success. I'd settle for being able to set the background color of the boxes in the legend to be clear so that the dashed lines are more obvious.
# quickchart-python https://github.com/typpo/quickchart-python
from quickchart import QuickChart
qc = QuickChart()
qc.width = 600
qc.height = 400
# Config can be set as a string or as a nested dict
qc.config = """{
"type": "line",
"data": {
"labels": [
"2015-16",
"2016-17",
"2017-18",
"2018-19",
"2019-20",
"2020-21",
"2021-22",
"2022-23",
"2023-24",
"2024-25",
"2025-26",
"2026-27",
"2027-28",
"2028-29",
"2029-30",
"2030-31",
"2031-32",
"2032-33",
"2033-34",
"2034-35",
"2035-36",
"2036-37",
"2037-38",
"2038-39",
"2039-40",
"2040-41",
"2041-42",
"2042-43",
"2043-44",
"2044-45",
"2045-46",
"2046-47",
"2047-48",
"2048-49"
],
"datasets": [
{
"label": "Emissions (actual)",
"borderColor": "rgb(192,0,0)",
"backgroundColor": "rgb(192,0,0)",
"pointBorderWidth": 0,
"pointBackgroundColor": "rgb(192,0,0)",
"pointStyle":"line",
"pointRadius": 0,
"fill": false,
"data": [
2250,2230,2195,2185,2170,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
],
"yAxisID": "y"
},
{
"label": "Emissions (projected)",
"borderColor": "rgb(192,0,0)",
"borderDash": [4,4],
"backgroundColor": "rgb(0,0,0)",
"pointBorderWidth": 0,
"pointBackgroundColor": "rgb(192,0,0)",
"pointStyle":"line",
"pointRadius": 0,
"fill": false,
"data": [
,,,,2170,2170,2170,2170,2170,2190,2200,2210,2210,2210,2210,2210,2210,2210,
2210,2210,2210,2210,2210,2210,2210,2210,2210,2210,2210,2210,2210,2210,2210,2210
],
"yAxisID": "y"
},
{
"label": "Sequestration (estimated)",
"borderColor": "rgb(0,112,192)",
"backgroundColor": "rgb(0,112,192)",
"pointBorderWidth": 2 ,
"pointBackgroundColor": "rgb(0,112,192)",
"pointStyle":"line",
"pointRadius": 0,
"fill": false,
"data": [
3197,3159,3121,3083,3008,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
],
"yAxisID": "y"
},
{
"label": "Sequestration (projected)",
"borderColor": "rgb(0,112,192)",
"borderDash": [4,4],
"backgroundColor": "rgb(0,112,192)",
"pointBorderWidth": 2,
"pointBackgroundColor": "rgba(0,112,192,0.1)",
"pointStyle":"line",
"pointRadius": 0,
"fill": false,
"data": [
,,,,3008,2970,2932,2894,2856,2818,2780,2742,2704,2666,2628,2590,2552,
2514,2476,2438,2400,2362,2324,2286,2248,2210,2172,2134,2096,2058,2020,
1982,1944,1906
],
"yAxisID": "y"
},
{
"label": "Cumulative balance (actual)",
"borderColor": "rgb(112,173,71)",
"backgroundColor": "rgb(112,173,71)",
"pointBorderWidth": 0,
"pointBackgroundColor": "rgb(112,173,71)",
"pointStyle":"line",
"pointRadius": 0,
"fill": true,
"data": [
947,1876,2802,3700,4538,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
],
"yAxisID": "y1"
},
{
"label": "Cumulative balance (projected)",
"borderColor": "rgba(112,173,71,0.4)",
"backgroundColor": "rgba(112,173,71,0.6)",
"pointBorderWidth": 0,
"pointBackgroundColor": "rgba(112,173,71,0.6)",
"pointStyle":"line",
"pointRadius": 0,
"fill": true,
"data": [
,,,,4538,5338,6100,6824,7510,8138,8718,9250,9744,10200,10618,10998,11340,11644,
11910,12138,12328,12480,12594,12670,12708,12708,12670,12594,12480,12328,12138,
11910,11644,11340
],
"yAxisID": "y1"
}
]
},
"options": {
"stacked": false,
"legend" : {
display: true,
position: 'bottom',
generateLabels(chart) {
return {
fillStyle: "rgb(255,255,255)"
}
}
},
"title": {
"display": false,
"text": "Chart.js Line Chart - Multi Axis"
},
"scales": {
"xAxes":[{
"ticks": {"fontFamily": "Calibri",
"fontSize": 9}
}],
"yAxes": [
{
"id": "y",
"type": "linear",
"display": true,
"position": "left",
"ticks": {
"min": 1000,
"max": 3500,
"stepSize": 500,
"fontFamily": "Calibri",
"fontSize": 9
},
"scaleLabel": {
"display": true,
"labelString": "Emissions and Sequestration - tCO2e per year",
"fontFamily": "Calibri",
"fontSize": 11
}
},
{
"id": "y1",
"type": "linear",
"display": true,
"position": "right",
"gridLines": {
"drawOnChartArea": false
},
"ticks": {
"min": 0,
"max": 14000,
"stepSize": 2000,
"fontFamily": "Calibri",
"fontSize": 9
},
"scaleLabel": {
"display": true,
"labelString": "Cumulative carbon balance - tCO2e",
"fontFamily": "Calibri",
"fontSize": 11
}
}
]
}
}
}"""
# You can get the chart URL...
print(qc.get_url())
# Get the image as a variable...
image = qc.get_image()
# Or write the chart to a file
qc.to_file('mychart.png')
This is because you putted the generateLabels function in the root of the legend options while it needs to be nested within the labels key like so:
options: {
legend: {
labels: {
generateLabels: (chart) => {
// Implementation
}
}
}
}
Documentation: https://www.chartjs.org/docs/2.9.4/configuration/legend.html#legend-label-configuration
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
"type": "scatter",
"data": {
"datasets": [
{
"label": "EARRINGS",
"data": [
{
"x": 13,
"y": "19-07-2021"
},
{
"x": 5,
"y": "12-08-2021"
}
],
"showLine": true,
"fill": false,
"borderColor": "rgb(125,60,122)"
},
{
"label": "RINGS",
"data": [
{
"x": 4,
"y": "09-08-2021"
},
{
"x": 1,
"y": "06-08-2021"
},
{
"x": 9,
"y": "12-08-2021"
}
],
"showLine": true,
"fill": false,
"borderColor": "rgb(125,60,122)"
},
{
"label": "BANGLES",
"data": [
{
"x": 2,
"y": "06-08-2021"
},
{
"x": 1,
"y": "12-08-2021"
}
],
"showLine": true,
"fill": false,
"borderColor": "rgb(125,60,122)"
},
{
"label": "NECKLACES",
"data": [
{
"x": 1,
"y": "12-08-2021"
}
],
"showLine": true,
"fill": false,
"borderColor": "rgb(125,60,122)"
}
]
},
"options": {
"scales": {
"x": {
"title": {
"display": true,
"text": "Date"
},
"ticks": {
"precision": 0,
"maxTicksLimit": 9
}
},
"y": {
"title": {
"display": true,
"text": "No of Trials"
},
"ticks": {
"precision": 0
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<canvas id="myChart"></canvas>
2 things, dont use an outdated version of the lib since your config wont work and the y scale is a linear scale by default so if you want to use strings you need to specify it as a category scale
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
"type": "scatter",
"data": {
"datasets": [
{
"label": "EARRINGS",
"data": [
{
"x": 13,
"y": "19-07-2021"
},
{
"x": 5,
"y": "12-08-2021"
}
],
"showLine": true,
"fill": false,
"borderColor": "rgb(125,60,122)"
},
{
"label": "RINGS",
"data": [
{
"x": 4,
"y": "09-08-2021"
},
{
"x": 1,
"y": "06-08-2021"
},
{
"x": 9,
"y": "12-08-2021"
}
],
"showLine": true,
"fill": false,
"borderColor": "rgb(125,60,122)"
},
{
"label": "BANGLES",
"data": [
{
"x": 2,
"y": "06-08-2021"
},
{
"x": 1,
"y": "12-08-2021"
}
],
"showLine": true,
"fill": false,
"borderColor": "rgb(125,60,122)"
},
{
"label": "NECKLACES",
"data": [
{
"x": 1,
"y": "12-08-2021"
}
],
"showLine": true,
"fill": false,
"borderColor": "rgb(125,60,122)"
}
]
},
"options": {
"scales": {
"x": {
"title": {
"display": true,
"text": "Date"
},
"ticks": {
"precision": 0,
"maxTicksLimit": 9
}
},
"y": {
type: 'category',
"title": {
"display": true,
"text": "No of Trials"
},
"ticks": {
"precision": 0
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.js"></script>
<canvas id="myChart"></canvas>
I am trying to use chartJS to create a stacked budget with an actual vs budgeted amount.
So I am aiming to create something like this.
I have gotten this far with it.
new Chart(document.getElementById("chartjs-7"), {
"type": "bar",
"data": {
"labels": ["Petrol", "Food", "Kids Clubs", "Alcohol"],
"datasets": [{
"label": "Actual Spend",
"data": [70, 100, 20, 29],
"borderColor": "rgb(63, 191, 63)",
"backgroundColor": "rgba(63, 191, 63)"
}, {
"label": "Budgeted amount",
"data": [60, 150, 20, 30],
"type": "bar",
"fill": false,
"borderColor": "rgb(63, 65, 191)",
"backgroundColor": "rgba(63, 65, 191)"
}]
},
"options": {
"scales": {
"yAxes": [{
"ticks": {
"beginAtZero": true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.min.js"></script>
<body>
<canvas id="chartjs-7" class="chartjs" width="770" height="385" style="display: block; width: 770px; height: 385px;"></canvas>
</body>
However mine currently appears like this.
Any ideas how to do this or if it is even possible with graphJS I can't seem to find a way to stack these against each other
You must add stacked: true to xAxes:
"options": {
"scales": {
"xAxes": [{
"stacked": true,
}],
"yAxes": [{
"ticks": {
"beginAtZero": true
}
}]
}
}
Demo:
new Chart(document.getElementById("chartjs-7"), {
"type": "bar",
"data": {
"labels": ["Petrol", "Food", "Kids Clubs", "Alcohol"],
"datasets": [{
"label": "Actual Spend",
"data": [70, 100, 20, 29],
"borderColor": "rgb(63, 191, 63)",
"backgroundColor": "rgba(63, 191, 63)"
}, {
"label": "Budgeted amount",
"data": [60, 150, 20, 30],
"type": "bar",
"fill": false,
"borderColor": "rgb(63, 65, 191)",
"backgroundColor": "rgba(63, 65, 191)"
}]
},
"options": {
"scales": {
"xAxes": [{
"stacked": true,
}],
"yAxes": [{
//"stacked": true,
"ticks": {
"beginAtZero": true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.min.js"></script>
<body>
<canvas id="chartjs-7" class="chartjs" width="770" height="385" style="display: block; width: 770px; height: 385px;"></canvas>
</body>
I have 4 different data sets data1, data2, data3, data4, each data set contain different dates, so date is not in order, hence graph is not displaying according to date
Here is my code
AmCharts.makeChart("chartdiv", {
"type": "serial",
"addClassNames": true,
"startDuration": 0.4,
"theme": "light",
"dataDateFormat": "YYYY-MM-DD",
"trendLines": [],
"applyGapValue": 0,
"graphs": [{
"bullet": "round",
"type": "smoothedLine",
"valueField": "data2",
}, {
"bullet": "round",
"type": "smoothedLine",
"valueField": "data1",
}, {
"bullet": "round",
"type": "smoothedLine",
"valueField": "data3",
}, {
"bullet": "round",
"type": "smoothedLine",
"valueField": "data4",
}],
"guides": [],
"valueAxes": [{
"id": "ValueAxis-1",
}],
"categoryField": "date",
"categoryAxis": {
"parseDates": true,
"equalSpacing": true,
"minorGridEnabled": true,
"gridPosition": "start",
},
"allLabels": [],
"balloon": {
"borderThickness": 3,
"horizontalPadding": 17,
"offsetX": 50,
"offsetY": 8
},
"chartCursor": {
"cursorAlpha": 0,
"cursorPosition": "mouse",
"graphBulletSize": 1,
"zoomable": false
},
"legend": {
"enabled": true,
"useGraphSettings": true,
"position": "top",
},
"dataProvider": [
{
"date": "2017-06-02",
"data1": 202,
}, {
"date": "2017-06-04",
"data1": 420,
}, {
"date": "2017-06-05",
"data1": 910,
}, {
"date": "2017-06-07",
"data1": 60,
},
{
"date": "2017-06-02",
"data2": 110,
}, {
"date": "2017-06-04",
"data2": 920,
}, {
"date": "2017-06-05",
"data2": 320,
}, {
"date": "2017-06-07",
"data2": 355,
},
{
"date": "2017-06-02",
"data3": 80,
}, {
"date": "2017-06-04",
"data3": 350,
}, {
"date": "2017-06-05",
"data3": 710,
}, {
"date": "2017-06-07",
"data3": 710,
},
{
"date": "2017-06-02",
"data4": 580,
}, {
"date": "2017-06-04",
"data4": 510,
}, {
"date": "2017-06-05",
"data4": 702,
}, {
"date": "2017-05-07",
"data4": 940,
}, {
"date": "2017-06-09",
"data4": 940,
},
]
});
html, body {
width: 100%;
height: 100%;
margin: 0px;
}
#chartdiv {
width: 100%;
height: 100%;
}
<script src="//www.amcharts.com/lib/3/amcharts.js"></script>
<script src="//www.amcharts.com/lib/3/serial.js"></script>
<script src="//www.amcharts.com/lib/3/themes/light.js"></script>
<div id="chartdiv"></div>
in the output I want chart to be displayed according to ordered date, thank you
You can sort the data like this:
chartData.sort(function(a, b) {
return new Date(b.date) - new Date(a.date);
});
Let's say you do this before passing it to the dataProvider property.
While you do have to sort the data by dates as previously mentioned, it's not enough for AmCharts. You also need to group the data by date as well or your chart will not render or behave correctly, i.e. the array element with the date "2017-06-02" needs to have the "data1", "data2", "data3", "data4" properties in the same element.
Here's one way to group it (assuming your data is in a variable called chartData):
var dataMap = {}; //map to group data by date
var newChartData = []; //new chart data array
chartData.forEach(function(dataItem) {
if (!dataMap[dataItem.date]) {
dataMap[dataItem.date] = {};
}
Object.keys(dataItem).forEach(function(key) { //assign keys to map
if (key !== "date") {
dataMap[dataItem.date][key] = dataItem[key];
dataMap[dataItem.date].date = dataItem.date;
}
});
});
//sort the dates and add the grouped objects to the new array.
Object.keys(dataMap).sort(function(lhs, rhs) {
return new Date(lhs) - new Date(rhs);
}).forEach(function(date) {
newChartData.push(dataMap[date]);
});
Demo:
var chartData = [
{
"date": "2017-06-02",
"data1": 202,
}, {
"date": "2017-06-04",
"data1": 420,
}, {
"date": "2017-06-05",
"data1": 910,
}, {
"date": "2017-06-07",
"data1": 60,
},
{
"date": "2017-06-02",
"data2": 110,
}, {
"date": "2017-06-04",
"data2": 920,
}, {
"date": "2017-06-05",
"data2": 320,
}, {
"date": "2017-06-07",
"data2": 355,
},
{
"date": "2017-06-02",
"data3": 80,
}, {
"date": "2017-06-04",
"data3": 350,
}, {
"date": "2017-06-05",
"data3": 710,
}, {
"date": "2017-06-07",
"data3": 710,
},
{
"date": "2017-06-02",
"data4": 580,
}, {
"date": "2017-06-04",
"data4": 510,
}, {
"date": "2017-06-05",
"data4": 702,
}, {
"date": "2017-05-07",
"data4": 940,
}, {
"date": "2017-06-09",
"data4": 940,
},
];
var dataMap = {}; //map to group data by date
var newChartData = []; //new chart data array
chartData.forEach(function(dataItem) {
if (!dataMap[dataItem.date]) {
dataMap[dataItem.date] = {};
}
Object.keys(dataItem).forEach(function(key) { //assign keys to map
if (key !== "date") {
dataMap[dataItem.date][key] = dataItem[key];
dataMap[dataItem.date].date = dataItem.date;
}
});
});
//sort the dates and add the grouped objects to the new array.
Object.keys(dataMap).sort(function(lhs, rhs) {
return new Date(lhs) - new Date(rhs);
}).forEach(function(date) {
newChartData.push(dataMap[date]);
});
AmCharts.makeChart("chartdiv", {
"type": "serial",
"addClassNames": true,
"startDuration": 0.4,
"theme": "light",
"dataDateFormat": "YYYY-MM-DD",
"trendLines": [],
"applyGapValue": 0,
"graphs": [{
"bullet": "round",
"type": "smoothedLine",
"valueField": "data2",
}, {
"bullet": "round",
"type": "smoothedLine",
"valueField": "data1",
}, {
"bullet": "round",
"type": "smoothedLine",
"valueField": "data3",
}, {
"bullet": "round",
"type": "smoothedLine",
"valueField": "data4",
}],
"guides": [],
"valueAxes": [{
"id": "ValueAxis-1",
}],
"categoryField": "date",
"categoryAxis": {
"parseDates": true,
"equalSpacing": true,
"minorGridEnabled": true,
"gridPosition": "start",
},
"allLabels": [],
"balloon": {
"borderThickness": 3,
"horizontalPadding": 17,
"offsetX": 50,
"offsetY": 8
},
"chartCursor": {
"cursorAlpha": 0,
"cursorPosition": "mouse",
"graphBulletSize": 1,
"zoomable": false
},
"legend": {
"enabled": true,
"useGraphSettings": true,
"position": "top",
},
"dataProvider": newChartData
});
html,
body {
width: 100%;
height: 100%;
margin: 0px;
}
#chartdiv {
width: 100%;
height: 100%;
}
<script src="//www.amcharts.com/lib/3/amcharts.js"></script>
<script src="//www.amcharts.com/lib/3/serial.js"></script>
<script src="//www.amcharts.com/lib/3/themes/light.js"></script>
<div id="chartdiv"></div>