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>
Multiple nested donut charts on the same page not working properly. I have two nested donut charts. One is showing ball0on text and another one is not. If I have 4 charts in first nested donut and two charts in second nested donut chart, balloon text will appear for last two outer charts in first and for both inner charts of the second donut.
Reference : Simulating nested donut chart using multiple pie chart instances
"Plugin: Manipulate z-index of the chart" is also there.
JSFIDDLE : PROBLEM STATEMENT
Hover on first nested donut chart inner pie charts, then hover on pie charts of second nested donut chart.
I didn't get any helpful data here : Documentation.
How to make balloon appear for all charts?
/**
* Plugin: Manipulate z-index of the chart
*/
AmCharts.addInitHandler(function(chart) {
// init holder for nested charts
if (AmCharts.nestedChartHolder === undefined)
AmCharts.nestedChartHolder = {};
if (chart.bringToFront === true) {
chart.addListener("init", function(event) {
// chart inited
var chart = event.chart;
var div = chart.div;
var parent = div.parentNode;
// add to holder
if (AmCharts.nestedChartHolder[parent] === undefined)
AmCharts.nestedChartHolder[parent] = [];
AmCharts.nestedChartHolder[parent].push(chart);
// add mouse mouve event
chart.div.addEventListener('mousemove', function() {
// calculate current radius
var x = Math.abs(chart.mouseX - (chart.realWidth / 2));
var y = Math.abs(chart.mouseY - (chart.realHeight / 2));
var r = Math.sqrt(x * x + y * y);
// check which chart smallest chart still matches this radius
var smallChart;
var smallRadius;
for (var i = 0; i < AmCharts.nestedChartHolder[parent].length; i++) {
var checkChart = AmCharts.nestedChartHolder[parent][i];
if ((checkChart.radiusReal < r) || (smallRadius < checkChart.radiusReal)) {
checkChart.div.style.zIndex = 1;
} else {
if (smallChart !== undefined)
smallChart.div.style.zIndex = 1;
checkChart.div.style.zIndex = 2;
smallChart = checkChart;
smallRadius = checkChart.radiusReal;
}
}
}, false);
});
}
}, ["pie"]);
/**
* Create the charts
*/
var pie1 = AmCharts.makeChart("chart1", {
"type": "pie",
"bringToFront": true,
"dataProvider": [{
"title": "$",
"value": 100,
"color": "#090E0F"
}],
"startDuration": 0,
"pullOutRadius": 0,
"color": "#fff",
"fontSize": 14,
"titleField": "title",
"valueField": "value",
"colorField": "color",
"labelRadius": -25,
"labelColor": "#fff",
"radius": 25,
"innerRadius": 0,
"labelText": "[[title]]",
"balloonText": "[[title]]: [[value]]"
});
var pie2 = AmCharts.makeChart("chart2", {
"type": "pie",
"bringToFront": true,
"dataProvider": [{
"title": "Marketing",
"value": 33,
"color": "#BA3233"
}, {
"title": "Production",
"value": 33,
"color": "#624B6A"
}, {
"title": "R&D",
"value": 33,
"color": "#6179C0"
}],
"startDuration": 1,
"pullOutRadius": 0,
"color": "#fff",
"fontSize": 9,
"titleField": "title",
"valueField": "value",
"colorField": "color",
"labelRadius": -28,
"labelColor": "#fff",
"radius": 80,
"innerRadius": 27,
"outlineAlpha": 1,
"outlineThickness": 4,
"labelText": "[[title]]",
"balloonText": "[[title]]: [[value]]"
});
var pie3 = AmCharts.makeChart("chart3", {
"type": "pie",
"bringToFront": true,
"dataProvider": [{
"title": "Online",
"value": 11,
"color": "#BA3233"
}, {
"title": "Print",
"value": 11,
"color": "#BA3233"
}, {
"title": "Other",
"value": 11,
"color": "#BA3233"
}, {
"title": "Equipment",
"value": 16.5,
"color": "#624B6A"
}, {
"title": "Materials",
"value": 16.5,
"color": "#624B6A"
}, {
"title": "Labs",
"value": 16.5,
"color": "#6179C0"
}, {
"title": "Patents",
"value": 16.5,
"color": "#6179C0"
}],
"startDuration": 1,
"pullOutRadius": 0,
"color": "#fff",
"fontSize": 8,
"titleField": "title",
"valueField": "value",
"colorField": "color",
"labelRadius": -27,
"labelColor": "#fff",
"radius": 135,
"innerRadius": 82,
"outlineAlpha": 1,
"outlineThickness": 4,
"labelText": "[[title]]",
"balloonText": "[[title]]: [[value]]"
});
var pi4 = AmCharts.makeChart("chart4", {
"type": "pie",
"bringToFront": true,
"dataProvider": [{
"title": "Design",
"value": 5.5,
"color": "#BA3233"
}, {
"title": "P&P",
"value": 5.5,
"color": "#BA3233"
}, {
"title": "Magazines",
"value": 11,
"color": "#BA3233"
}, {
"title": "Outdoor",
"value": 3.66,
"color": "#BA3233"
}, {
"title": "Promo",
"value": 3.66,
"color": "#BA3233"
}, {
"title": "Endorsement",
"value": 3.66,
"color": "#BA3233"
}, {
"title": "Maintenance",
"value": 8.25,
"color": "#624B6A"
}, {
"title": "Acquisition",
"value": 8.25,
"color": "#624B6A"
}, {
"title": "Raw",
"value": 5.5,
"color": "#624B6A"
}, {
"title": "Recycling",
"value": 5.5,
"color": "#624B6A"
}, {
"title": "Logistics",
"value": 5.5,
"color": "#624B6A"
}, {
"title": "LAB1",
"value": 3.3,
"color": "#6179C0"
}, {
"title": "LAB2",
"value": 3.3,
"color": "#6179C0"
}, {
"title": "LAB3",
"value": 3.3,
"color": "#6179C0"
}, {
"title": "Supply",
"value": 3.3,
"color": "#6179C0"
}, {
"title": "Disposal",
"value": 3.3,
"color": "#6179C0"
}, {
"title": "Application",
"value": 5.5,
"color": "#6179C0"
}, {
"title": "Acquisition",
"value": 5.5,
"color": "#6179C0"
}, {
"title": "Settlement",
"value": 5.5,
"color": "#6179C0"
}],
"startDuration": 1,
"pullOutRadius": 0,
"color": "#fff",
"fontSize": 8,
"titleField": "title",
"valueField": "value",
"colorField": "color",
"labelRadius": -27,
"labelColor": "#fff",
"radius": 190,
"innerRadius": 137,
"outlineAlpha": 1,
"outlineThickness": 4,
"labelText": "[[title]]",
"balloonText": "[[title]]: [[value]]",
"allLabels": [{
"text": "ACME Inc. Spending Chart",
"bold": true,
"size": 18,
"color": "#404040",
"x": 0,
"align": "center",
"y": 20
}]
});
var pie5 = AmCharts.makeChart("chart11", {
"type": "pie",
"bringToFront": true,
"dataProvider": [{
"title": "$",
"value": 100,
"color": "#090E0F"
}],
"startDuration": 0,
"pullOutRadius": 0,
"color": "#fff",
"fontSize": 14,
"titleField": "title",
"valueField": "value",
"colorField": "color",
"labelRadius": -25,
"labelColor": "#fff",
"radius": 25,
"innerRadius": 0,
"labelText": "[[title]]",
"balloonText": "[[title]]: [[value]]"
});
var pie6 = AmCharts.makeChart("chart22", {
"type": "pie",
"bringToFront": true,
"dataProvider": [{
"title": "Marketing",
"value": 33,
"color": "#BA3233"
}, {
"title": "Production",
"value": 33,
"color": "#624B6A"
}, {
"title": "R&D",
"value": 33,
"color": "#6179C0"
}],
"startDuration": 1,
"pullOutRadius": 0,
"color": "#fff",
"fontSize": 9,
"titleField": "title",
"valueField": "value",
"colorField": "color",
"labelRadius": -28,
"labelColor": "#fff",
"radius": 80,
"innerRadius": 27,
"outlineAlpha": 1,
"outlineThickness": 4,
"labelText": "[[title]]",
"balloonText": "[[title]]: [[value]]"
});
#charts,
#charts1 {
width: 200px;
height: 500px;
position: relative;
margin: 0 auto;
font-size: 8px;
flex: 1;
}
#charts {
width: 400px;
}
.chartdiv {
width: 400px;
height: 500px;
position: absolute;
top: 0;
left: 0;
}
#parent {
display: flex;
width: 700px;
border: 2px solid blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.amcharts.com/lib/3/amcharts.js"></script>
<script src="https://www.amcharts.com/lib/3/pie.js"></script>
<div id="parent">
<div id="charts">
<div id="chart1" class="chartdiv"></div>
<div id="chart2" class="chartdiv"></div>
<div id="chart3" class="chartdiv"></div>
<div id="chart4" class="chartdiv"></div>
</div>
<div id="charts1">
<div id="chart11" class="chartdiv"></div>
<div id="chart22" class="chartdiv"></div>
<div id="chart33" class="chartdiv"></div>
<div id="chart44" class="chartdiv"></div>
</div>
</div>
There's a bug with the nested plugin where it's using a reference to an element to hold a nest, which doesn't work when you have multiple sets of nested pie charts. A quick fix for this is to have it use the chart div's parent element ID to ensure that each set of pie charts are grouped correctly:
var parent = div.parentNode.id;
Of course this will add a dependency that the container div must have an ID but that's a small requirement.
You'll also want to remove the other divs if they don't have pie charts as they will prevent the mouseover event from firing on the second column's charts.
Updated code below:
/**
* Plugin: Manipulate z-index of the chart
*/
AmCharts.addInitHandler(function(chart) {
// init holder for nested charts
if (AmCharts.nestedChartHolder === undefined)
AmCharts.nestedChartHolder = {};
if (chart.bringToFront === true) {
chart.addListener("init", function(event) {
// chart inited
var chart = event.chart;
var div = chart.div;
var parent = div.parentNode.id; //changed to use the parent's ID instead of a reference.
// add to holder
if (AmCharts.nestedChartHolder[parent] === undefined) {
AmCharts.nestedChartHolder[parent] = [];
}
AmCharts.nestedChartHolder[parent].push(chart);
// add mouse mouve event
chart.div.addEventListener('mousemove', function() {
// calculate current radius
var x = Math.abs(chart.mouseX - (chart.realWidth / 2));
var y = Math.abs(chart.mouseY - (chart.realHeight / 2));
var r = Math.sqrt(x * x + y * y);
// check which chart smallest chart still matches this radius
var smallChart;
var smallRadius;
for (var i = 0; i < AmCharts.nestedChartHolder[parent].length; i++) {
var checkChart = AmCharts.nestedChartHolder[parent][i];
if ((checkChart.radiusReal < r) || (smallRadius < checkChart.radiusReal)) {
checkChart.div.style.zIndex = 1;
} else {
if (smallChart !== undefined)
smallChart.div.style.zIndex = 1;
checkChart.div.style.zIndex = 2;
smallChart = checkChart;
smallRadius = checkChart.radiusReal;
}
}
}, false);
});
}
}, ["pie"]);
/**
* Create the charts
*/
var pie1 = AmCharts.makeChart("chart1", {
"type": "pie",
"bringToFront": true,
"dataProvider": [{
"title": "$",
"value": 100,
"color": "#090E0F"
}],
"startDuration": 0,
"pullOutRadius": 0,
"color": "#fff",
"fontSize": 14,
"titleField": "title",
"valueField": "value",
"colorField": "color",
"labelRadius": -25,
"labelColor": "#fff",
"radius": 25,
"innerRadius": 0,
"labelText": "[[title]]",
"balloonText": "[[title]]: [[value]]"
});
var pie2 = AmCharts.makeChart("chart2", {
"type": "pie",
"bringToFront": true,
"dataProvider": [{
"title": "Marketing",
"value": 33,
"color": "#BA3233"
}, {
"title": "Production",
"value": 33,
"color": "#624B6A"
}, {
"title": "R&D",
"value": 33,
"color": "#6179C0"
}],
"startDuration": 1,
"pullOutRadius": 0,
"color": "#fff",
"fontSize": 9,
"titleField": "title",
"valueField": "value",
"colorField": "color",
"labelRadius": -28,
"labelColor": "#fff",
"radius": 80,
"innerRadius": 27,
"outlineAlpha": 1,
"outlineThickness": 4,
"labelText": "[[title]]",
"balloonText": "[[title]]: [[value]]"
});
var pie3 = AmCharts.makeChart("chart3", {
"type": "pie",
"bringToFront": true,
"dataProvider": [{
"title": "Online",
"value": 11,
"color": "#BA3233"
}, {
"title": "Print",
"value": 11,
"color": "#BA3233"
}, {
"title": "Other",
"value": 11,
"color": "#BA3233"
}, {
"title": "Equipment",
"value": 16.5,
"color": "#624B6A"
}, {
"title": "Materials",
"value": 16.5,
"color": "#624B6A"
}, {
"title": "Labs",
"value": 16.5,
"color": "#6179C0"
}, {
"title": "Patents",
"value": 16.5,
"color": "#6179C0"
}],
"startDuration": 1,
"pullOutRadius": 0,
"color": "#fff",
"fontSize": 8,
"titleField": "title",
"valueField": "value",
"colorField": "color",
"labelRadius": -27,
"labelColor": "#fff",
"radius": 135,
"innerRadius": 82,
"outlineAlpha": 1,
"outlineThickness": 4,
"labelText": "[[title]]",
"balloonText": "[[title]]: [[value]]"
});
var pi4 = AmCharts.makeChart("chart4", {
"type": "pie",
"bringToFront": true,
"dataProvider": [{
"title": "Design",
"value": 5.5,
"color": "#BA3233"
}, {
"title": "P&P",
"value": 5.5,
"color": "#BA3233"
}, {
"title": "Magazines",
"value": 11,
"color": "#BA3233"
}, {
"title": "Outdoor",
"value": 3.66,
"color": "#BA3233"
}, {
"title": "Promo",
"value": 3.66,
"color": "#BA3233"
}, {
"title": "Endorsement",
"value": 3.66,
"color": "#BA3233"
}, {
"title": "Maintenance",
"value": 8.25,
"color": "#624B6A"
}, {
"title": "Acquisition",
"value": 8.25,
"color": "#624B6A"
}, {
"title": "Raw",
"value": 5.5,
"color": "#624B6A"
}, {
"title": "Recycling",
"value": 5.5,
"color": "#624B6A"
}, {
"title": "Logistics",
"value": 5.5,
"color": "#624B6A"
}, {
"title": "LAB1",
"value": 3.3,
"color": "#6179C0"
}, {
"title": "LAB2",
"value": 3.3,
"color": "#6179C0"
}, {
"title": "LAB3",
"value": 3.3,
"color": "#6179C0"
}, {
"title": "Supply",
"value": 3.3,
"color": "#6179C0"
}, {
"title": "Disposal",
"value": 3.3,
"color": "#6179C0"
}, {
"title": "Application",
"value": 5.5,
"color": "#6179C0"
}, {
"title": "Acquisition",
"value": 5.5,
"color": "#6179C0"
}, {
"title": "Settlement",
"value": 5.5,
"color": "#6179C0"
}],
"startDuration": 1,
"pullOutRadius": 0,
"color": "#fff",
"fontSize": 8,
"titleField": "title",
"valueField": "value",
"colorField": "color",
"labelRadius": -27,
"labelColor": "#fff",
"radius": 190,
"innerRadius": 137,
"outlineAlpha": 1,
"outlineThickness": 4,
"labelText": "[[title]]",
"balloonText": "[[title]]: [[value]]",
"allLabels": [{
"text": "ACME Inc. Spending Chart",
"bold": true,
"size": 18,
"color": "#404040",
"x": 0,
"align": "center",
"y": 20
}]
});
var pie5 = AmCharts.makeChart("chart11", {
"type": "pie",
"bringToFront": true,
"dataProvider": [{
"title": "$",
"value": 100,
"color": "#090E0F"
}],
"startDuration": 0,
"pullOutRadius": 0,
"color": "#fff",
"fontSize": 14,
"titleField": "title",
"valueField": "value",
"colorField": "color",
"labelRadius": -25,
"labelColor": "#fff",
"radius": 25,
"innerRadius": 0,
"labelText": "[[title]]",
"balloonText": "[[title]]: [[value]]"
});
var pie6 = AmCharts.makeChart("chart22", {
"type": "pie",
"bringToFront": true,
"dataProvider": [{
"title": "Marketing",
"value": 33,
"color": "#BA3233"
}, {
"title": "Production",
"value": 33,
"color": "#624B6A"
}, {
"title": "R&D",
"value": 33,
"color": "#6179C0"
}],
"startDuration": 1,
"pullOutRadius": 0,
"color": "#fff",
"fontSize": 9,
"titleField": "title",
"valueField": "value",
"colorField": "color",
"labelRadius": -28,
"labelColor": "#fff",
"radius": 80,
"innerRadius": 27,
"outlineAlpha": 1,
"outlineThickness": 4,
"labelText": "[[title]]",
"balloonText": "[[title]]: [[value]]"
});
#charts,
#charts1 {
width: 200px;
height: 500px;
position: relative;
margin: 0 auto;
font-size: 8px;
flex: 1;
}
#charts {
width: 400px;
}
.chartdiv {
width: 400px;
height: 500px;
position: absolute;
top: 0;
left: 0;
}
#parent {
display: flex;
width: 700px;
border: 2px solid blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.amcharts.com/lib/3/amcharts.js"></script>
<script src="https://www.amcharts.com/lib/3/pie.js"></script>
<div id="parent">
<div id="charts">
<div id="chart1" class="chartdiv"></div>
<div id="chart2" class="chartdiv"></div>
<div id="chart3" class="chartdiv"></div>
<div id="chart4" class="chartdiv"></div>
</div>
<div id="charts1">
<div id="chart11" class="chartdiv"></div>
<div id="chart22" class="chartdiv"></div>
<!--
commented out as the mouseover event doesn't fire if there are empty divs overlapping
<div id="chart33" class="chartdiv"></div>
<div id="chart44" class="chartdiv"></div>
-->
</div>
</div>
I have a requirement where I need to use customlegends in XY Amcharts.
I have implemented them, but When I have added event listeners to those legends, the function wasnt triggered. I dont know the reason, can anyone correct me what I have made a mistake.
You can check the following link for the output:
jsfiddle.net/u371jyjs/3/
clickMarker is a legend-specific event, not a top-level chart event. Put the listener for it inside the legend object:
legend: {
// ...
listeners: [{
"event": "clickMarker",
"method": function(event) {
// toggle the marker state
event.dataItem.hidden = !event.dataItem.hidden;
event.chart.validateNow();
}
}]
}
Demo:
var chart = AmCharts.makeChart("chartdiv", {
"type": "xy",
"path": "https://www.amcharts.com/lib/3/",
"theme": "light",
"dataProvider": [{
"y": 10,
"x": 2,
"value": 59,
"y2": 5,
"x2": 3,
"value2": 44,
"label": "Hello",
"category": "0",
"column-1": 32
}, {
"y": 5,
"x": 8,
"value": 50,
"y2": 15,
"x2": 8,
"value2": 12,
"label": "Hi",
"category": "1000",
"column-1": 14
}, {
"y": 10,
"x": 8,
"value": 19,
"y2": 4,
"x2": 6,
"value2": 35,
"label": "Yo"
}, {
"y": 6,
"x": 5,
"value": 65,
"y2": 5,
"x2": 6,
"value2": 168,
"label": "Howdy"
}, {
"y": 15,
"x": 4,
"value": 92,
"y2": 13,
"x2": 8,
"value2": 102,
"label": "Hi there"
}, {
"y": 13,
"x": 1,
"value": 8,
"y2": 2,
"x2": 0,
"value2": 41,
"label": "Morning"
}, {
"y": 1,
"x": 6,
"value": 35,
"y2": 0,
"x2": 3,
"value2": 16,
"label": "Afternoon"
}],
"valueAxes": [{
"position": "bottom",
"axisAlpha": 0,
"integersOnly": true,
//"labelRotation": 45,
"labelFunction": function(value) {
// define categories
var cats = [
"Nick",
"Sarah",
"Kevin",
"Dominick",
"Christy",
"Kate",
"Julian",
"Anita",
"Mike",
"Kyle",
"Tyrese"
];
return cats[value];
}
}, {
"axisAlpha": 0,
"position": "left"
}],
"startDuration": 1.5,
"graphs": [{
"balloonText": "[[label]]",
"bullet": "circle",
"bulletBorderAlpha": 0.2,
"bulletAlpha": 0.8,
"lineAlpha": 0,
"fillAlphas": 0,
"valueField": "value",
"xField": "x",
"yField": "y",
"maxBulletSize": 100
}, {
"balloonText": "[[label]]",
"bullet": "diamond",
"bulletBorderAlpha": 0.2,
"bulletAlpha": 0.8,
"lineAlpha": 0,
"fillAlphas": 0,
"valueField": "value2",
"xField": "x2",
"yField": "y2",
"maxBulletSize": 100
}],
"legend": {
"switchable": true,
"textClickEnabled": true,
"data": [{
title: "One",
color: "#3366CC",
hidden: true
}, {
title: "Two",
color: "#FFCC33"
}],
"listeners": [{
"event": "clickMarker",
"method": function(event) {
event.dataItem.hidden = !event.dataItem.hidden;
event.chart.validateNow()
}
}]
}
});
html, body {
width: 100%;
height: 100%;
margin: 0;
}
#chartdiv {
width: 100%;
height: 100%;
}
<script src="https://www.amcharts.com/lib/3/amcharts.js"></script>
<script src="https://www.amcharts.com/lib/3/xy.js"></script>
<script src="https://www.amcharts.com/lib/3/themes/light.js"></script>
<div id="chartdiv"></div>
<div id="clicked">
</div>
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>
big edit
Having analyzed my situation, it seems to be another question / another scenario, more generally about saving to json.
So, I add a new Shapegroup to a layer on my stage with the following code:
...
var selectedShape, json = null;
...
function addNode(xPos, yPos)
{
//create the new node
var node = new Kinetic.Circle({
id: 'myRect',
x: xPos,
y: yPos,
radius: 30,
fill: '#FFFFFF',
stroke: '#000000',
strokeWidth: 4,
// test: "testattr"
});
// create the label
var label = new Kinetic.Text({
x: node.getX() - node.getRadius() + 10,
y: node.getY() + node.getRadius() + 4,
text: 'node',
fontSize: 12,
fontFamily: 'Arial',
fill: 'black',
});
// create group
var nodeGroup = new Kinetic.Group({
draggable: true
});
// add shapes to group
nodeGroup.add(node);
nodeGroup.add(label);
// add group to the layer
layer.add(nodeGroup);
// add layer to the stage
stage.add(layer);
/*
* Events for Nodes
* all events for the actual states / nodes
*/
// mouse over => red stroke
node.on('mouseover', function() {
$('body').css('cursor', 'pointer');
this.setStroke('red');
layer.draw();
});
// mouse out => back in black
node.on('mouseout', function() {
if(selectedShape != this){
console.log('mouseout fired, Position: ' + node.getX());
$('body').css('cursor', 'default');
this.setStroke('#000000');
writeMessage(messageLayer, node.getX()); // just for testing purposes
layer.draw();
}
});
node.on('click tap', function(){ //relevant
if(selectedShape != null){
$('body').css('cursor', 'default');
selectedShape.setStroke('#000000');
layer.draw();
}
selectedShape = null;
console.log('clicked');
selectedShape = this;
this.setStroke('red');
layer.draw();
});
/*
* Events for Node-labels
* events for labels
*/
label.on('mouseover', function() {
$('body').css('cursor', 'text');
this.setStroke('red');
this.setStrokeWidth(0.5)
layer.draw();
});
label.on('mouseout', function() {
$('body').css('cursor', 'default');
this.setStroke('');
this.setStrokeWidth(0);
layer.draw();
});
//change the Label of a node, return 'node' if nothing entered or cancelled.
label.on('click', function(){
var lblTxt = prompt('Neue Bezeichnung:', '');
if (lblTxt) {
this.setText(lblTxt);
} else {
this.setText('node');
}
layer.draw();
});
}
Having a button 'add new State' which actually adds a new group.
Code:
$('#createNode').click(function(e){
addNode(125, 125);
});
And a Button "remove State" which removes a selected nodegroup.
Code:
$('#removeNode').click(function(e){
if(selectedShape){
var selectedGroup = selectedShape.getParent();
selectedGroup.removeChildren();
selectedGroup.remove();
layer.draw();
} else {
writeMessage(messageLayer, 'No Object chosen');
}
});
Also, there's a button 'save to json' where I want to save all the actually remaining Shapes on my Stage.
Code:
$('#saveJSON').click(function(e){
json = null;
json = stage.toJSON();
console.log(json);
});
So, now I test the following cases:
Case 1: Save empty stage
JSON output:
{
"attrs": {
"width": 960,
"height": 600
},
"className": "Stage",
"children": [
{
"attrs": {},
"className": "Layer",
"children": []
}
]
}
Status: Seems to be OK.So, the formatting issue with the last } depends on stackoverflow, it should (and is) actually be included to code tag.
Case 2: Add one Node after Saving empty Stage (double-clicking / tapping or using button is no difference here). Save again.
JSON Output:
{
"attrs": {
"width": 960,
"height": 600
},
"className": "Stage",
"children": [
{
"attrs": {},
"className": "Layer",
"children": []
},
{
"attrs": {},
"className": "Layer",
"children": [
{
"attrs": {
"draggable": true
},
"className": "Group",
"children": [
{
"attrs": {
"id": "myRect",
"x": 125,
"y": 125,
"radius": 30,
"fill": "#FFFFFF",
"stroke": "#000000",
"strokeWidth": 4,
"test": "testattr"
},
"className": "Circle"
},
{
"attrs": {
"width": "auto",
"height": "auto",
"x": 105,
"y": 159,
"text": "node",
"fontSize": 12,
"fontFamily": "Arial",
"fill": "black"
},
"className": "Text"
}
]
}
]
}
]
}
Status: Why is there an empty Layer? But: One Group, two Objects, seems to be okay.
Case 3
Adding another Node. Save.
JSON Output:
{
"attrs": {
"width": 960,
"height": 600
},
"className": "Stage",
"children": [
{
"attrs": {},
"className": "Layer",
"children": []
},
{
"attrs": {},
"className": "Layer",
"children": [
{
"attrs": {
"draggable": true
},
"className": "Group",
"children": [
{
"attrs": {
"id": "myRect",
"x": 125,
"y": 125,
"radius": 30,
"fill": "#FFFFFF",
"stroke": "#000000",
"strokeWidth": 4,
"test": "testattr"
},
"className": "Circle"
},
{
"attrs": {
"width": "auto",
"height": "auto",
"x": 105,
"y": 159,
"text": "node",
"fontSize": 12,
"fontFamily": "Arial",
"fill": "black"
},
"className": "Text"
}
]
},
{
"attrs": {
"draggable": true,
"x": 206,
"y": 75,
"rotation": 0,
"scaleX": 1,
"scaleY": 1,
"offsetX": 0,
"offsetY": 0,
"skewX": 0,
"skewY": 0
},
"className": "Group",
"children": [
{
"attrs": {
"id": "myRect",
"x": 125,
"y": 125,
"radius": 30,
"fill": "#FFFFFF",
"stroke": "red",
"strokeWidth": 4,
"test": "testattr"
},
"className": "Circle"
},
{
"attrs": {
"width": "auto",
"height": "auto",
"x": 105,
"y": 159,
"text": "node",
"fontSize": 12,
"fontFamily": "Arial",
"fill": "black"
},
"className": "Text"
}
]
}
]
},
{
"attrs": {},
"className": "Layer",
"children": [
{
"attrs": {
"draggable": true
},
"className": "Group",
"children": [
{
"attrs": {
"id": "myRect",
"x": 125,
"y": 125,
"radius": 30,
"fill": "#FFFFFF",
"stroke": "#000000",
"strokeWidth": 4,
"test": "testattr"
},
"className": "Circle"
},
{
"attrs": {
"width": "auto",
"height": "auto",
"x": 105,
"y": 159,
"text": "node",
"fontSize": 12,
"fontFamily": "Arial",
"fill": "black"
},
"className": "Text"
}
]
},
{
"attrs": {
"draggable": true,
"x": 206,
"y": 75,
"rotation": 0,
"scaleX": 1,
"scaleY": 1,
"offsetX": 0,
"offsetY": 0,
"skewX": 0,
"skewY": 0
},
"className": "Group",
"children": [
{
"attrs": {
"id": "myRect",
"x": 125,
"y": 125,
"radius": 30,
"fill": "#FFFFFF",
"stroke": "red",
"strokeWidth": 4,
"test": "testattr"
},
"className": "Circle"
},
{
"attrs": {
"width": "auto",
"height": "auto",
"x": 105,
"y": 159,
"text": "node",
"fontSize": 12,
"fontFamily": "Arial",
"fill": "black"
},
"className": "Text"
}
]
}
]
}
]
}
Status: Here you can see the first occurence of my problem: All the objects on my stage are doubled in my JSON file on two different layers. So they are tripled and so on when adding more objects. My Problem: I want to add a data model and use the data with a database, so I think this is pretty messy but I have no clue where I went wrong.
** case 4**
Removing all but one node from my stage:
JSON Output:
{
"attrs": {
"width": 960,
"height": 600
},
"className": "Stage",
"children": [
{
"attrs": {},
"className": "Layer",
"children": []
},
{
"attrs": {},
"className": "Layer",
"children": [
{
"attrs": {
"draggable": true
},
"className": "Group",
"children": [
{
"attrs": {
"id": "myRect",
"x": 125,
"y": 125,
"radius": 30,
"fill": "#FFFFFF",
"stroke": "#000000",
"strokeWidth": 4,
"test": "testattr"
},
"className": "Circle"
},
{
"attrs": {
"width": "auto",
"height": "auto",
"x": 105,
"y": 159,
"text": "node",
"fontSize": 12,
"fontFamily": "Arial",
"fill": "black"
},
"className": "Text"
}
]
}
]
},
{
"attrs": {},
"className": "Layer",
"children": [
{
"attrs": {
"draggable": true
},
"className": "Group",
"children": [
{
"attrs": {
"id": "myRect",
"x": 125,
"y": 125,
"radius": 30,
"fill": "#FFFFFF",
"stroke": "#000000",
"strokeWidth": 4,
"test": "testattr"
},
"className": "Circle"
},
{
"attrs": {
"width": "auto",
"height": "auto",
"x": 105,
"y": 159,
"text": "node",
"fontSize": 12,
"fontFamily": "Arial",
"fill": "black"
},
"className": "Text"
}
]
}
]
}
]
}
Status: Again, the remaining nodes are doubled.
** case 5**: Removing all nodes, having an empty stage again (after adding 2 nodes, then removing them)
JSON Output:
{
"attrs": {
"width": 960,
"height": 600
},
"className": "Stage",
"children": [
{
"attrs": {},
"className": "Layer",
"children": []
},
{
"attrs": {},
"className": "Layer",
"children": []
},
{
"attrs": {},
"className": "Layer",
"children": []
}
]
}
Status: Stage is empty, but layers still remaining. Not that nice.
Conclusion: I think I'm doing something pretty wrong. It's a lot of JSON in this question and I hope someone actually reads through this and may help me figuring out what I did wrong. Would be so great.
Best regards,
Dominik
another edit
Problem seems for me in addnode-function, using stage.add(layer); to add new shapegroups. A different way to add new groups to one layer would be much appreciated for I am fairly new to kineticjs and don't know it yet.
So, after writing out this Question, rewriting the whole question, adding another edit after further investigaten, I actually found my problem and I think I want to share it with you:
At the addnode-function, i called stage.add(layer) - as the code says, it adds a new layer for each new Shapegroup. This caused the behaviour I explained in the question.
Now I removed stage.add(layer) from addNode to my init()-function which is only called at startup. At addNode, I now just say layer.add(nodeGroup); layer.draw(); and it works like a charm now. Sorry for the inconvenience :( I had a knot in my brain.