amcharts group by days and minutes - javascript

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.

Related

Amcharts 3D charts - category axis getting mixed with the value axis wrongly

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>

Adding last values to the legends in AmCharts Graph

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]]"
}

Offset guides label in case of text overlapping in amcharts

I would like to include guides into my amcharts graphs and I found very descriptive examples. However I'm struggling with positioning of label text, especially in case when guides are so close that labels overlap.
Here is example code https://jsfiddle.net/Tripy/1wwygcy7/2/
HTML:
<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/amstock.js"></script>
<div id="chartdiv" style="width: 100%; height: 500px;"></div>
Javascript:
var chartData = weekendGuides = [];
generateChartData();
function generateChartData() {
var firstDate = new Date();
firstDate.setDate( firstDate.getDate() - 200 );
firstDate.setHours( 0, 0, 0, 0 );
for ( var i = 0; i < 200; i++ ) {
var newDate = new Date( firstDate );
newDate.setDate( newDate.getDate() + i );
var a1 = Math.round( Math.random() * ( 40 + i ) ) + 100 + i;
var b1 = Math.round( Math.random() * ( 1000 + i ) ) + 500 + i * 2;
chartData.push( {
"date": newDate,
"value": a1,
"volume": b1
} );
// add weekend guide
if ( 6 == newDate.getDay() ) {
var toDate = new Date( newDate );
toDate.setDate( newDate.getDate() + 2 );
weekendGuides.push( {
"date": newDate,
"toDate": toDate,
"lineAlpha": 0,
"fillAlpha": 0.05,
"fillColor": "#000",
"expand": true
} );
}
}
}
var chart = AmCharts.makeChart( "chartdiv", {
"type": "stock",
"dataSets": [ {
"title": "first data set",
"fieldMappings": [ {
"fromField": "value",
"toField": "value"
}, {
"fromField": "volume",
"toField": "volume"
} ],
"dataProvider": chartData,
"categoryField": "date"
} ],
"panels": [ {
"showCategoryAxis": false,
"title": "Value",
"percentHeight": 70,
"stockGraphs": [ {
"id": "g1",
"valueField": "value",
"comparable": true,
"compareField": "value",
"balloonText": "[[title]]:<b>[[value]]</b>",
"compareGraphBalloonText": "[[title]]:<b>[[value]]</b>"
} ],
"stockLegend": {
"periodValueTextComparing": "[[percents.value.close]]%",
"periodValueTextRegular": "[[value.close]]"
},
"categoryAxis": {
"guides": weekendGuides
},
"valueAxes": [ {
"guides": [ {
"value": 325,
"lineAlpha": 0.8,
"lineColor": "#0c0",
"label": "Guide #1",
"position": "right"
}, {
"value": 322,
"lineAlpha": 0.8,
"lineColor": "#0c0",
"label": "Guide #2",
"position": "right"
}]
} ]
} ],
"chartScrollbarSettings": {
"graph": "g1"
},
"chartCursorSettings": {
"valueBalloonsEnabled": true,
"fullWidth": true,
"cursorAlpha": 0.1
},
"periodSelector": {
"position": "bottom",
"periods": [ {
"period": "MM",
"selected": true,
"count": 1,
"label": "1 month"
}, {
"period": "YYYY",
"count": 1,
"label": "1 year"
}, {
"period": "YTD",
"label": "YTD"
}, {
"period": "MAX",
"label": "MAX"
} ]
}
} );
Any idea how to push label text below the guide for guides in case that labels are overlapping. Perhaps with CSS code for class name amcharts-guide-[id]?
There isn't a way to do this through the guide properties properties, but you have the right hunch with the css class name. Set addClassNames to true, give your guides IDs and then add a drawn event listener in your stock panel that adjusts the desired guide(s) directly by calling querySelector on the .amcharts-guide-[id] tspan selector and adjusting the y attribute:
AmCharts.makeChart("chartdiv", {
"addClassNames": true,
// ...
"stockPanels": [{
"valueAxes": [{
"guides": [{
"id": "guide-1",
// ..
}, {
"id": "guide-2",
// ..
}]
}],
"listeners": [{
"event": "drawn",
"method": function() {
var guide2Text = document.querySelector('.amcharts-guide-guide-2 tspan');
if (guide2Text) {
guide2Text.setAttribute('y', 20);
}
}
}]
}],
// ..
});
Updated fiddle

Chart displaying without without any point when only one point available

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

AmChart: Change label color of axis

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

Categories