I'm using AmChart to make a serial graph and I want to set a different color for the last category label.
Does somebody know how this is possible?
This my code to create the graph and return validateData().
var chart = AmCharts.makeChart("historyContent", {
"type": "serial",
"theme": "light",
"dataProvider": loadDataProvider(tag),
"valueAxes": [{
"gridColor": "#FFFFFF",
"gridAlpha": 0.2,
"dashLength": 0
}],
"gridAboveGraphs": true,
"graphs": [{
"balloonText": "[[p_type]] | [[p_date]]: <b>[[value]]</b>",
"fillAlphas": 0.8,
"lineAlpha": 0.2,
"type": "column",
"valueField": "value"
}],
"chartCursor": {
"categoryBalloonEnabled": false,
"cursorAlpha": 0,
"zoomable": false
},
"categoryField": "period",
"categoryAxis": {
"gridPosition": "start",
"gridAlpha": 0,
"tickPosition": "start",
"tickLength": 20,
"labelFunction": function(valueText, serialDataItem, categoryAxis) {
var p_type = valueText.substring(valueText.length - 10, 0);
var p_date = valueText.substring(valueText.length - 10);
console.log(valueText);
valueText = p_type + "\n" + p_date;
return valueText;
}
}
});
return chart.validateData();
In amCharts 4:
const valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.renderer.labels.template.fill = am4core.color("#A0CA92");
See the official codepen example
You can use categoryAxis.labelColorField to specify which field in your data holds the color for category axis labels.
var chart = AmCharts.makeChart("historyContent", {
"type": "serial",
"theme": "light",
"dataProvider": loadDataProvider(tag),
"valueAxes": [{
"gridColor": "#FFFFFF",
"gridAlpha": 0.2,
"dashLength": 0
}],
"gridAboveGraphs": true,
"graphs": [{
"balloonText": "[[p_type]] | [[p_date]]: <b>[[value]]</b>",
"fillAlphas": 0.8,
"lineAlpha": 0.2,
"type": "column",
"valueField": "value"
}],
"chartCursor": {
"categoryBalloonEnabled": false,
"cursorAlpha": 0,
"zoomable": false
},
"categoryField": "period",
"categoryAxis": {
"labelColorField": "color", // specifies which field in data holds color for label
"gridPosition": "start",
"gridAlpha": 0,
"tickPosition": "start",
"tickLength": 20,
"labelFunction": function(valueText, serialDataItem, categoryAxis) {
var p_type = valueText.substring(valueText.length - 10, 0);
var p_date = valueText.substring(valueText.length - 10);
console.log(valueText);
valueText = p_type + "\n" + p_date;
return valueText;
}
}
});
If you you need to color just the last label, you would set that field on your last data point. I.e.:
[{
period: "First",
value: 100
}, {
period: "Second",
value: 200
}, {
period: "Third",
value: 300
}, {
period: "Last",
value: 400,
color: "#cc0000"
}];
Here's a working example:
http://codepen.io/amcharts/pen/02ffa4178c069262b705abbf17bba5dc
Related
I am using amcharts with 3D (i.e. depth3D=40), the chart comes up good but the category axis is getting overlapped/merged with the value axis
I am using something like this :
var chart = AmCharts.makeChart("chartdiv", {
"type": "serial",
"theme": "light",
"startDuration": 1,
"valueAxes": [{
"id": "v1",
"title": "Cost (in USD)",
"position": "left",
"autoGridCount": false,
"labelFunction": function(value) {
return "$" + Math.round(value);
}
}, {
"id": "v2",
"title": "Effort ( hh:mm )",
"gridAlpha": 0,
"position": "right",
"autoGridCount": false,
"duration": "mm",
"durationUnits": {
"hh": "h ",
"mm": "min"
}
}],
---------------------
---------------------
"depth3D": 40,
"angle": 10,
"chartCursor": {
"pan": true,
"cursorPosition": "mouse",
"cursorAlpha": 0.1,
"cursorColor": "#000000",
"fullWidth": true,
"valueLineAlpha": 0.2
},
"categoryField": "lob",
"categoryAxis": {
"gridPosition": "start",
"axisAlpha":0.9,
"axisThickness": 1,
"axisColor": "black",
"gridAlpha":0,
"labelRotation":25,
"fontSize":10,
"boldLabels":true
},
Here is my fiddle
It's the value axis(in red color) getting merged/mixed with the category axis.
Any suggestions to avoid the axis merging/overlapping would be highly appreciated!
When you have 3D enabled using angle/depth3D, the chart perspective is shifted. The red line you're seeing is part of the value axis line that is extended into 3D space due to the new perspective, so it's by design; note that the other axis does this too if you set the angle in the opposite direction. As a result, there isn't a way to remove this using the config. As a hack, you can try editing the SVG directly through the drawn event by querying the axis line by class/id with addClassNames set to true and modifying the d attribute:
function remove3DSegment() {
var line = document.querySelector('.value-axis-v2 .amcharts-axis-line');
var lineSVG = line.getAttribute('d');
line.setAttribute('d', lineSVG.substr(0, lineSVG.lastIndexOf(' '))); //last part of the SVG path command contains the 3D segment on the bottom
}
var chart = AmCharts.makeChart("chartdiv", {
"type": "serial",
"theme": "light",
"startDuration": 1,
"addClassNames": true,
// ...
"listeners": [{
"event": "drawn",
"method": remove3DSegment
}],
// ...
});
If you want to generalize it, you can have the function look for the chart's id and value axis' id through the event.
function remove3DSegment(e) {
var divId = e.chart.div.id;
var valueAxisId = e.chart.valueAxes[1].id; //assumes your second axis is the one that needs to be modified.
var line = document.querySelector('#' + divId + ' .value-axis-' + valueAxisId + ' .amcharts-axis-line');
var lineSVG = line.getAttribute('d');
line.setAttribute('d', lineSVG.substr(0, lineSVG.lastIndexOf(' '))); //last part of the SVG path command contains the 3D segment on the bottom
}
Note that this is a hack and if the SVG path command for drawing the axis gets changed in a future v3 release, then this may likely break.
function remove3DSegment() {
var line = document.querySelector('.value-axis-v2 .amcharts-axis-line');
var lineSVG = line.getAttribute('d');
line.setAttribute('d', lineSVG.substr(0, lineSVG.lastIndexOf(' ')));
}
var chart = AmCharts.makeChart("chartdiv", {
"type": "serial",
"theme": "light",
"startDuration": 1,
"addClassNames": true,
"valueAxes": [{
"id": "v1",
"title": "Cost (in USD)",
"position": "left",
"autoGridCount": false,
"labelFunction": function(value) {
return "$" + Math.round(value);
}
}, {
"id": "v2",
"title": "Effort ( hh:mm )",
"gridAlpha": 0,
"position": "right",
"axisAlpha": 0.9,
"axisThickness": 2,
"axisColor": "red",
}],
"graphs": [{
"id": "g4",
"valueAxis": "v1",
"lineColor": "#3B7610",
"fillColors": "#3B7610",
"fillAlphas": 1,
"type": "column",
"title": "Cost saving per year",
"valueField": "costSaving",
"clustered": false,
"columnWidth": 0.3,
"topRadius": 1,
// "legendValueText": "$[[value]]M",
"balloonText": "[[title]]<br /><b style='font-size: 90%'>$[[value]]M</b>"
}, {
"id": "g1",
"valueAxis": "v2",
"bullet": "round",
"bulletBorderAlpha": 1,
"bulletColor": "#FFFFFF",
"bulletSize": 5,
"hideBulletsCount": 50,
"lineThickness": 2,
"lineColor": "#20acd4",
"type": "smoothedLine",
"title": "Effort saving per year",
"topRadius": 0.95,
"useLineColorForBulletBorder": true,
"valueField": "effortSaving",
"balloonText": "[[title]]<br /><b style='font-size: 90%'>[[value]]</b>"
}],
"depth3D": 40,
"angle": 10,
"chartCursor": {
"pan": true,
"cursorPosition": "mouse",
"cursorAlpha": 0.1,
"cursorColor": "#000000",
"fullWidth": true,
"valueLineAlpha": 0.2
},
"categoryField": "lob",
"categoryAxis": {
"gridPosition": "start",
"axisAlpha": 0.9,
"axisThickness": 1,
"axisColor": "black",
"gridAlpha": 0,
"labelRotation": 25,
"fontSize": 10,
"boldLabels": true
},
"legend": {
"horizontalGap": 5,
"maxColumns": 30,
"useGraphSettings": true,
"markerSize": 10,
"leftMargin": 0,
"valueText": ""
},
"balloon": {
"borderThickness": 1,
"shadowAlpha": 0
},
"export": {
"enabled": true
},
"listeners": [{
"event": "drawn",
"method": remove3DSegment
}],
"dataProvider": [{
"lob": "abca",
"effortSaving": 64140,
"costSaving": 3600
}, {
"lob": "dfasdf",
"effortSaving": 326724,
"costSaving": 1875
}, {
"lob": "dfgsdfgt",
"effortSaving": 36864,
"costSaving": 1500,
}, {
"lob": "gfsdg",
"effortSaving": 101808,
"costSaving": 3614,
}, {
"lob": "fgfgf",
"effortSaving": 13200,
"costSaving": 6215,
}, {
"lob": "jytujty",
"effortSaving": 111312,
"costSaving": 3123,
}, {
"lob": "erqwr",
"effortSaving": 5040,
"costSaving": 1235,
}]
});
#chartdiv {
width: 100%;
height: 500px;
}
<script src="https://www.amcharts.com/lib/3/amcharts.js"></script>
<script src="https://www.amcharts.com/lib/3/serial.js"></script>
<script src="https://www.amcharts.com/lib/3/plugins/export/export.min.js"></script>
<link rel="stylesheet" href="https://www.amcharts.com/lib/3/plugins/export/export.css" type="text/css" media="all" />
<script src="https://www.amcharts.com/lib/3/pie.js"></script>
<script src="https://www.amcharts.com/lib/3/themes/light.js"></script>
<div id="chartdiv"></div>
I'm getting some "undefined" values on the Amcharts when is rendered in a small window:
But the same graph, without reloading, if I move it to a bigger screen I got the values correctly:
Why is happening that?
This is some of the code of my graph:
funciones.chart = AmCharts.makeChart("chartdiv", {
"type": "serial",
"theme": "light",
"precision":"3",
"decimalSeparator": ",",
"thousandsSeparator": ".",
"legend": {
"horizontalGap": 10,
"maxColumns": 3,
"position": "top",
"useGraphSettings": false,
"markerSize": 10,
"marginTop": 20,
"autoMargins":true,
"forceWidth":true,
"valueAlign":"right",
"labelWidth":85,
"valueWidth":85
},
"dataProvider": response,
"synchronizeGrid":true,
"valueAxes": [{
"axisAlpha": 0,
"position": "left",
"title": "Activos"
}],
"graphs": graphs,
"chartScrollbar": {},
"chartCursor": {
"cursorPosition": "mouse"
},
"categoryField": "diahora",
"chartCursor": {
"fullWidth": true,
"cursorAlpha": 0.1,
"listeners": [{
"event": "zoomed",
"method": function(ev) {
var value = funciones.chart.valueAxes;
var uno = funciones.chart.dataProvider[value[0].start];
var dos = funciones.chart.dataProvider[value[0].end];
}
}]
},
"categoryAxis": {
"gridPosition": "start",
"axisColor": "#DADADA",
},
"export": {
"enabled": true,
"position": "top-right",
"class": "export-main",
"menu": [ {
"title": "Exportar el gráfico a archivo de imagen",
"label": "Descargar",
"menu": [ "PNG", "JPG", "PDF" ]
}]
}
});
EDIT: hell! The data actually is badly made... I don't know why but in only 1 case the JSON comes with a blank array [] between the values:
[{"fecha":"2018-09-01","hora":"00:00:00","dia":1,"diahora":"1-00:00:00","cen_name":"AIHUAPI_______013","descripcion":"Rerversa 52ET2","activo_actual":"393.54786432893"},[],{"fecha":"2018-09-01","hora":"00:15:00","dia":1,"diahora":"1-00:15:00","cen_name":"AIHUAPI_______013","descripcion":"Rerversa 52ET2","activo_actual":"405.51075393844"},[], etc...
But in the rest are ok, as:
[{"fecha":"2018-01-01","hora":"00:00:00","dia":1,"diahora":"1-00:00:00","cen_name":"AIHUAPI_______013","descripcion":"Rerversa 52ET2","activo_actual":"179.64412533621"},{"fecha":"2018-01-01","hora":"00:15:00","dia":1,"diahora":"1-00:15:00","cen_name":"AIHUAPI_______013","descripcion":"Rerversa 52ET2","activo_actual":"169.2686290587"}, etc...
I am in the situation where people can choose between many different time intervals like
1d (5minute data)
1year (1day data)
If I put this in "groupToPeriods": ["DD"] it will display the days perfectly when it is etc 1-year data.
If I put this in "groupToPeriods": ["NN"] it will display the minutes perfectly when it is etc 1-day data.
Days
Minutes
How do I make it work both with NN and DD at the same time? should I automatically put in either NN or DD depending on which type of data I provide? This is not the case in one of the other sample charts I've tried there it did it automatically, however, that was not one of the stock charts, but normal charts.
I tried this "groupToPeriods": ["DD-NN"] and "groupToPeriods": ["DD", "NN"] without any luck, here and here is some documentation ive read about grouping and date formatting.
var redaw = false;
var logarithmic = false;
var interval = "all";
function createChart1(chartData) {
var chart = AmCharts.makeChart("chartdivs", {
"type": "stock",
"theme": "light",
"recalculateToPercents": "never",
"dataSets": [{
"title": "$",
"fieldMappings": [{
"fromField": "value",
"toField": "value"
}, {
"fromField": "volume",
"toField": "volume"
}],
"dataProvider": chartData,
"categoryField": "date",
"color": "#2e4259",
"fillAlphas": 0.5
}],
"panels": [{
"title": "Fiat",
"showCategoryAxis": false,
"percentHeight": 70,
"color": "#fff",
"recalculateToPercents": "never",
"stockGraphs": [{
"id": "g1",
"valueField": "value",
"comparable": true,
"lineThickness": "3px",
"compareField": "value",
"balloonText": "[[title]]:<b>[[value]]</b>",
"compareGraphBalloonText": "[[title]]:<b>[[value]]</b>",
"color": "#fff"
}]
}, {
"title": "Volume",
"percentHeight": 30,
"color": "#fff",
"stockGraphs": [{
"valueField": "volume",
"type": "line",
"showBalloon": false,
"fillAlphas": 0.5
}],
"stockLegend": {
"periodValueTextRegular": "[[value.close]]",
"marginRight": 10,
"color": "#fff"
}
}],
"panelsSettings": {
// "color": "#fff",
"plotAreaBorderAlpha": 0.5,
"plotAreaBorderColor": "#2e4259",
"marginLeft": 30,
"marginRight": 30,
"marginTop": 5,
"marginBottom": 30
},
"categoryAxesSettings": {
"equalSpacing": true,
"gridColor": "#2e4259",
"gridAlpha": 0.5,
"maxSeries": 1,
//////////////////////////////////// HERE IS THE PROBLEM ////////////////////////////////////
"groupToPeriods": ["DD-NN"]
},
"valueAxesSettings": {
"logarithmic": logarithmic,
"gridColor": "#2e4259",
"gridAlpha": 0.5,
"inside": false,
"showLastLabel": false
},
"chartScrollbarSettings": {
"graph": "g1",
// "graphFillColor": "#000",
"backgroundColor": "transparent",
"gridAlpha": 0,
"graphFillAlpha": 0.8,
"graphLineAlpha": 0,
"graphLineColor": "#fff",
"graphType": "line",
"updateOnReleaseOnly": false,
"graphFillColor": "#2e4259",
"selectedBackgroundColor": "#2e4259",
"selectedGraphFillAlpha": 0,
"selectedGraphFillColor": "#2e4259"
},
"chartCursorSettings": {
"valueBalloonsEnabled": true,
"fullWidth": false,
"cursorAlpha": 0.5,
"valueLineBalloonEnabled": false,
"valueLineEnabled": false,
"cursorColor": "#000"
}
});
redaw === true ? chart.validateData() : redaw = true;
}
function generateChartData() {
var chartData1 = [];
// current date
var firstDate = new Date();
// now set 500 minutes back
firstDate.setMinutes(firstDate.getDate() - 1000);
var CSRFToken = document.getElementById("CSRFToken").value;
var parameters = "CSRFToken=" + CSRFToken + "&interval=" + interval + "&id=" + 1;
console.log("INTERVAL: " + interval);
ajax("/pages/ajax/request-chart-data.php", parameters, "POST", false, function(results) {
if (results) {
var jsonObj = JSON.parse(results);
console.log("JSON OBJ");
console.log(jsonObj);
for (var i in jsonObj) {
var newDate = new Date(jsonObj[i].date);
chartData1.push({
"date": newDate,
"value": jsonObj[i].price,
"volume": jsonObj[i].volume
});
}
createChart1(chartData1);
} else {
console.log("NO RESULTS");
}
});
}
generateChartData();
No, this isn't possible. groupToPeriods groups data based on whatever your maxSeries is set to in period ascending order; using the default value as an example, - first it starts with seconds (ss), then 10 seconds (10ss), 30 seconds (30ss), then minutes (mm), 10 minutes (10mm), 30 minutes (30mm) then days (DD), weeks (WW), months (MM) then years (YYYY). You can't combine multiple periods in one grouping, so in your case, with your extremely small maxSeries setting, set it to the smallest period you want to group to based on your data. Also note that there is no NN period - it's mm for minutes. You also need to set an appropriate minPeriod as well, which also takes a single period type, to ensure that your data is rendered correctly as well.
Is there a way to add last values in the graph to the legend names when not hover over the AmCharts graph ?
Here is a code pen with a demo chart.
https://codepen.io/anon/pen/LxmLaL
Here is the js code
var chartData = generateChartData();
var chart = AmCharts.makeChart("chartdiv", {
"type": "serial",
"theme": "light",
"legend": {
"periodValueText":"last"
},
"dataProvider": chartData,
"synchronizeGrid":true,
"valueAxes": [{
"id":"v1",
"axisColor": "#FF6600",
"axisThickness": 2,
"axisAlpha": 1,
"position": "left"
}, {
"id":"v2",
"axisColor": "#FCD202",
"axisThickness": 2,
"axisAlpha": 1,
"position": "right"
}, {
"id":"v3",
"axisColor": "#B0DE09",
"axisThickness": 2,
"gridAlpha": 0,
"offset": 50,
"axisAlpha": 1,
"position": "left"
}],
"graphs": [{
"valueAxis": "v1",
"lineColor": "#FF6600",
"bullet": "round",
"bulletBorderThickness": 1,
"hideBulletsCount": 30,
"title": "red line",
"valueField": "visits",
"fillAlphas": 0
}, {
"valueAxis": "v2",
"lineColor": "#FCD202",
"bullet": "square",
"bulletBorderThickness": 1,
"hideBulletsCount": 30,
"title": "yellow line",
"valueField": "hits",
"fillAlphas": 0
}, {
"valueAxis": "v3",
"lineColor": "#B0DE09",
"bullet": "triangleUp",
"bulletBorderThickness": 1,
"hideBulletsCount": 30,
"title": "green line",
"valueField": "views",
"fillAlphas": 0
}],
"chartScrollbar": {},
"chartCursor": {
"cursorPosition": "mouse"
},
"categoryField": "date",
"categoryAxis": {
"parseDates": true,
"axisColor": "#DADADA",
"minorGridEnabled": true
}
});
chart.addListener("dataUpdated", zoomChart);
zoomChart();
// generate some random data, quite different range
function generateChartData() {
var chartData = [];
var firstDate = new Date();
firstDate.setDate(firstDate.getDate() - 100);
for (var i = 0; i < 100; i++) {
// we create date objects here. In your data, you can have date strings
// and then set format of your dates using chart.dataDateFormat property,
// however when possible, use date objects, as this will speed up chart rendering.
var newDate = new Date(firstDate);
newDate.setDate(newDate.getDate() + i);
var visits = Math.round(Math.sin(i * 5) * i);
var hits = Math.round(Math.random() * 80) + 500 + i * 3;
var views = Math.round(Math.random() * 6000) + i * 4;
chartData.push({
date: newDate,
visits: visits,
hits: hits,
views: views
});
}
return chartData;
}
function zoomChart(){
chart.zoomToIndexes(chart.dataProvider.length - 20, chart.dataProvider.length - 1);
}
I believe it has something to do with periodValueText but I'm unable to figure out how to achieve the same. Any help would be appreciated.
You have correctly pointed out that periodValueText needs to be used. You just need to use double-bracketed meta codes in it. For close value it's [[value.close]]:
"legend": {
"periodValueText":"[[value.close]]"
}
I am using AmSerialChart to display chart data. It is working fine when chart data has more than one value. If chart data has only one value, the point and category axis are not displaying. For example, in the below code if I iterate the for loop with more than 1, the points and axis will display fine. But if I set to 1, the point and axis are not displaying. http://jsfiddle.net/arpd17uf/
var chartData = generatechartData();
function generatechartData() {
var chartData = [];
var firstDate = new Date();
for ( var i = 0; i < 1; i++ ) {
var newDate = new Date( firstDate );
newDate.setTime( newDate.getTime() + (i * 60 * 1000) );
var visits = Math.round( Math.random() * 90 - 45 );
chartData.push( {
date: newDate,
visits: visits
} );
}
return chartData;
}
var chart = AmCharts.makeChart( "chartdiv", {
"theme": "light",
"type": "serial",
"dataProvider": chartData,
"dataDateFormat": "YYYY-MM-DD JJ:NN:SS",
"valueAxes": [ {
"inside": true,
"axisAlpha": 0
} ],
"graphs": [ {
"id": "g1",
"balloonText": "<div style='margin:5px; font-size:19px;'><span style='font-size:13px;'>[[category]]</span><br>[[value]]</div>",
"bullet": "round",
"bulletBorderAlpha": 1,
"bulletBorderColor": "#FFFFFF",
"hideBulletsCount": 50,
"lineThickness": 2,
"lineColor": "#fdd400",
"negativeLineColor": "#67b7dc",
"valueField": "visits"
} ],
"chartScrollbar": {
},
"chartCursor": {},
"categoryField": "date",
"categoryAxis": {
"parseDates": true,
"axisAlpha": 0,
"minHorizontalGap": 55,
"dashLength": 1,
"minorGridEnabled": true,
"position": "top",
"minPeriod": "fff"
},
"listeners": [ {
"event": "dataUpdated",
"method": function() {
if ( chart ) {
if ( chart.zoomToIndexes ) {
chart.zoomToIndexes( 130, chartData.length - 1 );
}
}
}
} ]
} );
Your minPeriod is too small. Your data is in minute intervals, going by your setTime calculations, so you'll want to set it to minutes ("mm"), rather than milliseconds ("fff").
"categoryAxis": {
// ... omitted
"minPeriod": "mm"
},
Updated fiddle