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...
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 want to replicate the following example.
When I try to access the chartBoard property I receive an error that this object is undefined.
rendereMethod(e) {
console.log("rendered")
var sb = e.chart.chartScrollbar.set.node;
sb.addEventListener("mousedown", function() {
e.chart.mouseIsDown = true;
});
e.chart.chartDiv.addEventListener("mouseup", function() {
e.chart.mouseIsDown = false;
// zoomed finished
console.log("zoom finished", e.chart.lastZoomed);
});
},
That is weird because chartScrollbar doesn't have any events or methods according to docs.
This is the options of my graph
this.chart = window.AmCharts.makeChart("chartdiv", {
"path": AmCharts_path,
"type": "stock",
"theme": "light",
"componentRef": this,
"mouseWheelZoomEnabled": true,
"dataSets": this.$store.state.portfoliosData.performance.map(function (port, idx) {
return {
"title": port.name,
"fieldMappings": [{
"fromField": "value",
"toField": "value"
}],
"dataProvider": port.data,
"compared": (idx === 0 ? false : true),
"categoryField": "date"
}
}),
"panels": [{
"title": "Value",
"percentHeight": 70,
"componentRef": this,
"stockGraphs": [
{
"id": "g1",
"valueField": "value",
"comparable": true,
"compareField": "value",
"balloonFunction": this.ballonRender,
"compareGraphBalloonFunction": this.ballonRender
}],
}],
"chartScrollbarSettings": {
"markPeriodChange": true,
"usePeriod": "DD",
"autoGridCount": true,
"graph": "g1",
"scrollbarHeight": 40
},
"categoryAxis": {
"parseDates": true,
},
"categoryAxesSettings": {
"groupToPeriods": ["DD"]
},
"balloon": {
"fixedPosition": true,
"maxWidth": 10000,
"offsetY": 1,
},
"dataDateFormat": "YYYY-MM-DD",
"chartCursorSettings": {
"valueBalloonsEnabled": true,
"categoryBalloonEnabled": true,
"selectWithoutZooming": true,
"showNextAvailable": true,
"categoryBalloonAlpha": 0.8,
"bulletsEnabled": true,
"bulletSize": 10,
"valueZoomable":true,
"usePeriod": "DD",
"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:'EEEE, MMM DD'},
{period:'WW',format:'EEEE, MMM DD'},
{period:'MM',format:'MMM'},
{period:'YYYY',format:'YYYY'}
]
},
"listeners": [
{
"event": "zoomed",
"method": this.calulateMetrics
},
{
"event": "init",
"method": this.initPeriod
},
{
"event": "rendered",
"method": this.rendereMethod
}
],
"periodSelector": {
"position": "bottom"
},
});
Reproduction code is here
Although the example code is for serial graphs, I guess it should be fine for stock 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 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
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