AmCharts Legend / Filter Configuration? - javascript

I'm working on a data intensive IOT project, and we are using many different AmCharts to display our data to the user. I just implemented a line chart with a legend and it's working very well. I have about 20 different assets being displayed, and they are different colors. The way AmCharts implements their legend is, when you click a color it is disabled.
My question is can these be reversed easily? I want it so, when you click a assets color on the legend all the others on the chart are disabled, and the one you clicked is the only one being displayed.
Thanks for the help in advance.

You can use the showItem and hideItem events in the legend to force the clicked on marker to maintain its visibility by setting the graph's hidden property to false and hide the other graphs by setting hidden to true:
// in makeChart:
"legend": {
"enabled": true,
// ...
"listeners": [{
"event": "showItem",
"method": hideOthers
}, {
"event": "hideItem",
"method": hideOthers
}]
},
// ...
function hideOthers(e) {
var currentGraph = e.dataItem;
currentGraph.hidden = false; //force clicked graph to stay visible
e.chart.graphs.forEach(function(graph) {
if (graph.id !== currentGraph.id) {
graph.hidden = true; //hide the others
}
});
// update the chart with newly set hidden values
e.chart.validateNow();
}
Demo below:
function hideOthers(e) {
var currentGraph = e.dataItem;
currentGraph.hidden = false; //force clicked graph to stay visible
e.chart.graphs.forEach(function(graph) {
if (graph.id !== currentGraph.id) {
graph.hidden = true; //hide the others
}
});
// update the chart with newly set hidden values
e.chart.validateNow();
}
AmCharts.makeChart("chartdiv", {
"type": "serial",
"categoryField": "category",
"startDuration": 1,
"categoryAxis": {
"gridPosition": "start"
},
"trendLines": [],
"graphs": [{
"balloonText": "[[title]] of [[category]]:[[value]]",
"bullet": "round",
"id": "AmGraph-1",
"title": "graph 1",
"valueField": "column-1"
},
{
"balloonText": "[[title]] of [[category]]:[[value]]",
"bullet": "square",
"id": "AmGraph-2",
"title": "graph 2",
"valueField": "column-2",
"hidden": true
}
],
"guides": [],
"valueAxes": [{
"id": "ValueAxis-1",
"stackType": "regular",
"title": "Axis title"
}],
"allLabels": [],
"balloon": {},
"legend": {
"enabled": true,
"useGraphSettings": true,
"listeners": [{
"event": "showItem",
"method": hideOthers
}, {
"event": "hideItem",
"method": hideOthers
}]
},
"titles": [{
"id": "Title-1",
"size": 15,
"text": "Chart Title"
}],
"dataProvider": [{
"category": "category 1",
"column-1": 8,
"column-2": 5
},
{
"category": "category 2",
"column-1": 6,
"column-2": 7
},
{
"category": "category 3",
"column-1": 2,
"column-2": 3
},
{
"category": "category 4",
"column-1": 1,
"column-2": 3
},
{
"category": "category 5",
"column-1": 2,
"column-2": 1
},
{
"category": "category 6",
"column-1": 3,
"column-2": 2
},
{
"category": "category 7",
"column-1": 6,
"column-2": 8
}
]
});
<script type="text/javascript" src="https://www.amcharts.com/lib/3/amcharts.js"></script>
<script type="text/javascript" src="https://www.amcharts.com/lib/3/serial.js"></script>
<div id="chartdiv" style="width: 100%; height: 400px; background-color: #FFFFFF;"></div>
Edit
To make it so that clicking on the same marker toggles the visibility of the other charts back on, you can store a couple of flags in the chart instance itself through the event handler and use those flags to determine whether to hide all other charts or make them all visible:
function hideOthers(e) {
var currentGraph = e.dataItem;
var hidden = true;
//check if we clicked on this graph before and if all the other graphs are visible.
// if we clicked on this graph before and the other graphs are invisible,
// make them visible, otherwise default to previous behavior
if (e.chart.lastClicked == currentGraph.id && e.chart.allVisible == false) {
hidden = false;
e.chart.allVisible = true;
}
else {
e.chart.allVisible = false;
}
e.chart.lastClicked = currentGraph.id; //keep track of the current one we clicked
currentGraph.hidden = false; //force clicked graph to stay visible
e.chart.graphs.forEach(function(graph) {
if (graph.id !== currentGraph.id) {
graph.hidden = hidden; //set the other graph's visibility based on the rules above
}
});
// update the chart with newly set hidden values
e.chart.validateNow();
}
AmCharts.makeChart("chartdiv", {
// .. custom flags to make the above code work
"lastClicked": null,
"allVisible": true, //if you're only showing one graph by default, set this to false
// ...
})
Demo:
function hideOthers(e) {
var currentGraph = e.dataItem;
var hidden = true;
//check if we clicked on this graph before and if all the other graphs are visible.
// if we clicked on this graph before and the other graphs are invisible,
// make them visible, otherwise default to previous behavior
if (e.chart.lastClicked == currentGraph.id && e.chart.allVisible == false) {
hidden = false;
e.chart.allVisible = true;
}
else {
e.chart.allVisible = false;
}
e.chart.lastClicked = currentGraph.id; //keep track of the current one we clicked
currentGraph.hidden = false; //force clicked graph to stay visible
e.chart.graphs.forEach(function(graph) {
if (graph.id !== currentGraph.id) {
graph.hidden = hidden; //set the other graph's visibility based on the rules above
}
});
// update the chart with newly set hidden values
e.chart.validateData();
}
AmCharts.makeChart("chartdiv", {
"type": "serial",
"lastClicked": null,
"allVisible": true, //if you're only showing one graph by default, set this to false
"categoryField": "category",
"startDuration": 1,
"categoryAxis": {
"gridPosition": "start"
},
"trendLines": [],
"graphs": [{
"balloonText": "[[title]] of [[category]]:[[value]]",
"bullet": "round",
"id": "AmGraph-1",
"title": "graph 1",
"valueField": "column-1"
},
{
"balloonText": "[[title]] of [[category]]:[[value]]",
"bullet": "square",
"id": "AmGraph-2",
"title": "graph 2",
"valueField": "column-2"
}
],
"guides": [],
"valueAxes": [{
"id": "ValueAxis-1",
//"includeHidden": true,
"title": "Axis title"
}],
"allLabels": [],
"balloon": {},
"legend": {
"enabled": true,
"useGraphSettings": true,
"listeners": [{
"event": "showItem",
"method": hideOthers
}, {
"event": "hideItem",
"method": hideOthers
}]
},
"titles": [{
"id": "Title-1",
"size": 15,
"text": "Chart Title"
}],
"dataProvider": [{
"category": "category 1",
"column-1": 8,
"column-2": 5
},
{
"category": "category 2",
"column-1": 6,
"column-2": 7
},
{
"category": "category 3",
"column-1": 2,
"column-2": 3
},
{
"category": "category 4",
"column-1": 1,
"column-2": 3
},
{
"category": "category 5",
"column-1": 2,
"column-2": 1
},
{
"category": "category 6",
"column-1": 3,
"column-2": 2
},
{
"category": "category 7",
"column-1": 6,
"column-2": 8
}
]
});
<script type="text/javascript" src="https://www.amcharts.com/lib/3/amcharts.js"></script>
<script type="text/javascript" src="https://www.amcharts.com/lib/3/serial.js"></script>
<div id="chartdiv" style="width: 100%; height: 400px; background-color: #FFFFFF;"></div>

Related

How to add trendline to line chart highcharts in JSON

im currently struggling to create a trend line to a line chart. found some old solutions and those things didn't work for me.
Current code:
{
"key": "003",
"title": "Detections",
"type": "chart",
"chartData": {
"chart": {
"type": "line",
"renderTo": "container"
},
"title": {
"text": ""
},
"subtitle": {
"text": ""
},
"xAxis": {
"categories": ["Jan 7", "Jan 14", "Jan 21", "Jan 28",
"Feb 4","Feb 11","Feb 18","Feb 25",
"Mar 4","Mar 11","Mar 18","Mar 28",
"Apr 1","Apr 8","Apr 15","Apr 22","Apr 29",
"May 6","May 13","May 20","May 27"
]
},
"colors": [ "#f89c1b"],
"yAxis": {
"title": {
"text": "Number of Exits"
}
},
"plotOptions": {
"line": {
"dataLabels": {
"enabled": true
},
"enableMouseTracking": false
}
},
"series": [{
"name": "Week",
"data": [60,12,29,48,
24,31,15,37,
32,16,22,29,
21,13,9,14,15,
10,12,13,7]
}
]
},
"index": 2,
"defaultWidth": "100%"
}
Current chart:
enter image description here
How do i add trend line to this line chart? is there any built in parameter to add trend line?
First, load and initialize indicators and trendline modules. Then add new trendline series. For example:
series: [{
id: "mainSeries",
name: "Week",
data: [...]
}, {
type: 'trendline',
linkedTo: "mainSeries"
}]
Live demo: https://codesandbox.io/s/highcharts-react-demo-fork-wubgnd?file=/demo.jsx
API Reference: https://api.highcharts.com/highstock/series.trendline

Group x axis labels

I need to group (and show) labels of X axis of a grahp, but still showing all single labels.
This is the code I actually use, and its a normal column2d graph:
FusionCharts.ready(function() {
var myChart = new FusionCharts({
type: "column2d",
renderAt: "chart",
width: "100%",
height: "100%",
dataFormat: "json",
dataSource: {
"chart": {
"animation": 0,
"caption": "Graph title",
"xAxisName": "Performance",
"baseFontColor": "#000000",
},
"data": [
{
"label": "351-08",
"value": "91"
},
{
"label": "351-09",
"value": "90"
},
{
"label": "351-10",
"value": "94"
},
{
"label": "351-01",
"value": "99"
},
{
"label": "351-07",
"value": "92"
},
{
"label": "351-06",
"value": "81"
},
],
"trendlines": [
{
"line": [
{
"startvalue": "82",
"color": "#ff3333",
"thickness": "5",
"valueOnRight": "1",
"displayvalue": "Average"
}
]
}
]
}
}).render();
});
What I need is showing another label on X axis that groups labels.
For example:
Group 1: [label1, label2];
Group 2: [label3, label4, label5];
Group 3: [label6];
UPDATED
I attached an image of what I need.
As you can see I need another labels line ("Fattore1", "Fattore2" and "Fattore3") that group other labels.

Amcharts: category data is not shown while changing the cursor

In an Amstock examples (1,2) I saw that the category field block is enabled during moving a cursor.
However I didn't manage to replicate this logic in my project
My chartCursorSettings are following
this.chart = window.AmCharts.makeChart("chartdiv", {
"path": AmCharts_path,
"type": "stock",
"theme": "light",
"dataSets": portfolioData.map(function (port, idx) {
return {
"title": port.name,
"fieldMappings": [{
"fromField": "value",
"toField": "value"
}],
"dataProvider": port.data,
"compared": (idx === 0 ? false : true),
"categoryField": "date"
}
}),
"panels": [{
"showCategoryAxis": false,
"title": "Value",
"percentHeight": 70,
"stockGraphs": [
{
"id": "g1",
"valueField": "value",
"comparable": true,
"compareField": "value",
"balloonFunction": this.ballonRender,
"compareGraphBalloonFunction": this.ballonRender
}]
}],
"chartScrollbarSettings": {
"graph": "g1"
},
"categoryAxis": {
"parseDates": true
},
"balloon": {
"fixedPosition": true,
"maxWidth": 10000
},
"chartCursorSettings": {
"valueBalloonsEnabled": true,
"categoryBalloonEnabled": true,
"categoryBalloonAlpha": 0.2,
"bulletsEnabled": true,
"bulletSize": 10,
"categoryBalloonDateFormats": [
{period:'fff',format:'JJ:NN:SS'},
{period:'ss',format:'JJ:NN:SS'},
{period:'mm',format:'JJ:NN'},
{period:'hh',format:'JJ:NN'},
{period:'DD',format:'MMM DD'},
{period:'WW',format:'MMM DD'},
{period:'MM',format:'MMM'},
{period:'YYYY',format:'YYYY'}
]
},
"listeners": [{
"event": "zoomed",
"method": this.calulateMetrics
}],
"periodSelector": {
"position": "bottom",
"periods": [{
"period": "MM",
"count": 1,
"label": "1 month"
}, {
"period": "MM",
"count": 3,
"label": "3 month"
}, {
"period": "MM",
"count": 6,
"label": "6 month"
}, {
"period": "YYYY",
"count": 1,
"label": "1 year"
}, {
"period": "YTD",
"label": "YTD"
}, {
"period": "MAX",
"selected": true,
"label": "All"
}]
},
});
},
Also I set parseDates to true
"categoryAxis": {
"parseDates": true
},
I tried to specify the "dataDateFormat": "YYYY-MM-DD" but it didn't help me either.
How can I enable this field?
I pass the JavaScript Date object to category field.
The categoryBalloon from the chartCursor requires that the categoryAxis be visible. Setting showCategoryAxis: false in your panel effectively removes the balloon since you're removing the category axis.
If you don't want the categoryAxis labels but want the category balloon, set labelsEnabled to false in your categoryAxesSettings.
AmCharts.makeChart("...", {
// ...
panels: [{
//showCategoryAxis: false, //comment/remove this
// ...
}],
// ...
categoryAxesSettings: {
labelsEnabled: false //if you want to remove the axis labels but keep the balloon
},
// ...
});
Demo
Some helpful clarifications:
categoryAxis doesn't do anything at the top level of the stock chart and all stock charts has parseDates enabled by default. categoryAxesSettings is the equivalent in this case.
dateDateFormat tells AmCharts how to parse your string-based dates in your dataProvider. Since you're using Date objects, this doesn't do anything.

How to get value outside click function

I have a div of a map and a div of pie chart on the web page. There are several pins on the map, and I want to refresh the chart div based on different click.
Here is the click function of leaflet.js:
var country = "";
map.on('click', function(e) {
country = "Worldwide";
alert("Set map to worldwide");
});
markerUS.on('click', function(e) {
country = "U.S.";
alert('U.S');
});
in the chart.js (pie chart):
AmCharts.makeChart("chartdiv1", {
"type": "pie",
"angle": 12,
"balloonText": "[[title]]<br><span style='font-size:14px'><b>[[value]]</b> ([[percents]]%)</span>",
"depth3D": 15,
"titleField": "category",
"valueField": "column-1",
"allLabels": [],
"balloon": {},
"legend": {
"enabled": true,
"align": "center",
"markerType": "circle"
},
"titles": [{
"id": "Title-1",
"size": 15,
"text": "Number of Projects distribution of " + country
}],
"dataProvider": [{
"category": "a",
"column-1": 8
},
{
"category": "b",
"column-1": 6
},
{
"category": "c",
"column-1": 2
},
{
"category": "d",
"column-1": "3"
},
{
"category": "e",
"column-1": "4"
},
{
"category": "f",
"column-1": "2"
}
]
});
inside "titles" I make country as variable based on the pin I clicked.
But I got country is undefined and the value country from leaflet.js seems didn't pass to chart.js. Why? How to correct this and realize the function?
You got undefined country because its value only be initialized when user click on map or on a maker. You could try to update your code like this
map.on('click', function(e) {
var country = "Worldwide";
makeChart(country);
});
markerUS.on('click', function(e) {
var country = "U.S.";
makeChart(country);
});
function makeChart(country) {
AmCharts.makeChart("chartdiv1", {
// your chart option ....
});
}
As Trung said you need to call a function that refrech the chart on each click event
var country = "";
map.on('click', function(e) {
country = "Worldwide";
refrechChart(country);
});
markerUS.on('click', function(e) {
country = "U.S.";
refrechChart(country);
});
and then make the refrechChart function
function refrechChart(country) {
AmCharts.makeChart("chartdiv1", {
"type": "pie",
"angle": 12,
"balloonText": "[[title]]<br><span style='font-size:14px'><b>[[value]]</b> ([[percents]]%)</span>",
"depth3D": 15,
"titleField": "category",
"valueField": "column-1",
"allLabels": [],
"balloon": {},
"legend": {
"enabled": true,
"align": "center",
"markerType": "circle"
},
"titles": [{
"id": "Title-1",
"size": 15,
"text": "Number of Projects distribution of " + country
}],
"dataProvider": [{
"category": "a",
"column-1": 8
},
{
"category": "b",
"column-1": 6
},
{
"category": "c",
"column-1": 2
},
{
"category": "d",
"column-1": "3"
},
{
"category": "e",
"column-1": "4"
},
{
"category": "f",
"column-1": "2"
}
]
});
}
you can also pass more parameter to use in your chart like
function refrechChart(country,value1,value2) {
//...
}

Why does my Kendo Grid's model-calculated field show the function's code?

I have the following Kendo UI Grid setup with a calculated field in the model.
When executed, this grid loads up properly but displays the actual source code of the model's cost function in each cell rather than the expected calculated value:
If I click on an individual cell, it does actually show the calculated value:
The aggregate footer row always show the same code, I'm unable to get it to print a value.
I've posted a running example at Kendo's dojo.
<div id="item_65_lineItems" data-field-name="item[65][lineItems]"></div>
<script>
jQuery(function(){
var json = {
"columns": [{
"field": "line_no",
"title": "Line No.",
"width": "15%"
}, {
"field": "description",
"title": "Description",
"width": "60%"
}, {
"field": "qty",
"title": "Qty",
"width": "10%",
"footerTemplate": "Sum: #=sum#"
}, {
"field": "cost",
"title": "Cost",
"width": "15%",
"footerTemplate": "Sum: #=sum#"
}],
"dataSource": {
"data": [{
"line_no": 1,
"description": "Test line item",
"qty": 15
}, {
"line_no": 1.1,
"description": "test 1",
"qty": 12
}, {
"line_no": 2,
"description": "test 2",
"qty": 16
}, {
"line_no": 3,
"description": "test 3",
"qty": 15
}, {
"line_no": 4,
"description": "test 4",
"qty": 12
}, {
"qty": 12,
"line_no": 5,
"description": "test 5"
}],
"aggregate": [{
"field": "qty",
"aggregate": "sum"
}, {
"field": "cost",
"aggregate": "sum"
}]
},
"editable": {
"createAt": "bottom"
},
"pageable": false,
"toolbar": [{
"name": "create"
}]
};
json.dataSource.schema = {
model: {
cost: function () {
return this.qty * 100;
}
}
};
//json.dataSource = new kendo.data.DataSource(json.dataSource);
console.log(json);
jQuery("#item_65_lineItems").kendoGrid(json);
});
</script>
you can use a template to execute the function:
{
"field": "cost",
"title": "Cost",
"width": "15%",
"footerTemplate": "Sum: #=sumCosts()#",
"template": "#=cost()#"
}
the footer seems to be trickier, but you can call a different function to get the value:
var sumCosts = function () {
var ds = $("#item_65_lineItems").data("kendoGrid").dataSource;
var aggregates = ds.aggregates();
return aggregates.qty.sum * 100;
};
here's a sample

Categories

Resources