Offset guides label in case of text overlapping in amcharts - javascript

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

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>

Amcharts: chartScrollbar is undefined in event callback

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

Uncaught TypeError: dp[ds.categoryField].setFullYear is not a function at Object.AmCharts.baseYearInitialize

In Amcharts Stock chart, I am trying to show data, i'm getting this data in json form from the database. The error it is showing, "Uncaught TypeError: dp[ds.categoryField].setFullYear is not a function at Object.AmCharts.baseYearInitialize".
JSON array is fine, and also if i keep only one dataset, then it works fine, as soon as i enter a year, whose data i have already in json form, it shows me an error.
var chart;
var SER = [];
//var SER;
first();
function first() {
for (var i = 0; i < 5; i++) {
generateChartData(2000 + i);
}
//SER = JSON.stringify(SER1);
//console.log(SER1);
dd();
}
function generateChartData(year) {
var firstDate = new Date(year, 0, 1);
var temp = [];
for (var i = 0; i < 365; i++) {
var newDate = new Date(firstDate);
newDate.setDate(newDate.getDate() + i);
newDate = ((newDate.getMonth() + 1) < 10 ? "0" + (newDate.getMonth() + 1) : (newDate.getMonth() + 1)) +
"-" + (newDate.getDate() < 10 ? "0" + newDate.getDate() : newDate.getDate()) +
"-" + year;
temp.push({
date: newDate,
value: Math.round(Math.random() * (40 + i)) + 100 + i
});
}
SER.push(temp);
}
function dd() {
AmCharts.addInitHandler(function(chart) {
AmCharts.baseYearInitialize = function(chart) {
for (var x = 0; x < chart.dataSets.length; x++) {
var ds = chart.dataSets[x];
if (ds.baseYear !== undefined) {
for (var i = 0; i < ds.dataProvider.length; i++) {
var dp = ds.dataProvider[i]; dp[ds.categoryField].setFullYear(ds.baseYear);
}
}
}
}
AmCharts.baseYearInitialize(chart);
}, ["stock"]);
chart = AmCharts.makeChart("chartdiv", {
"type": "stock",
"theme": "light",
"dataSets": [{
"title": "2000",
"fieldMappings": [{
"fromField": "value",
"toField": "value"
}],
"dataProvider": SER[0],
"categoryField": "date"
}
/* keeping more than one dataset showing error
, {
"title": "2001",
"fieldMappings": [{
"fromField": "value",
"toField": "value"
}],
"dataProvider": SER[1],
"categoryField": "date",
"compared": true,
"baseYear": 2000
}, {
"title": "2002",
"fieldMappings": [{
"fromField": "value",
"toField": "value"
}
*/
],
"panels": [{
"title": "Value",
"categoryAxis": {},
"dateFormats": 'DD-MM-YYYY',
"stockGraphs": [{
"id": "g1",
"valueField": "value",
"lineThickness": 2,
"comparable": true,
"compareField": "value",
"balloonText": "[[title]]:<b>[[value]]</b>",
"compareGraphBalloonText": "[[title]]:<b>[[value]]</b>",
"compareGraph": {
"dashLength": 5,
"lineThickness": 2
}
}],
"stockLegend": {
"periodValueTextComparing": "[[percents.value.close]]%",
"periodValueTextRegular": "[[value.close]]"
}
}],
"panelsSettings": {
"recalculateToPercents": "never"
},
"chartScrollbarSettings": {
"graph": "g1"
},
"chartCursorSettings": {
"valueBalloonsEnabled": true,
"fullWidth": true,
"cursorAlpha": 0.1,
"valueLineBalloonEnabled": true,
"valueLineEnabled": true,
"valueLineAlpha": 0.5
},
"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"
}]
}
});
$('document').ready(function() {
$('#submit').on('click', function() {
add(document.getElementById('year').value);
});
});
}
function add(yr) {
chart.dataSets.push({
"title": yr,
"fieldMappings": [{
"fromField": "value",
"toField": "value"
}],
"dataProvider": SER[yr-2000],
"categoryField": "date",
"compared": true,
"baseYear": 2000
});
AmCharts.baseYearInitialize(chart);
chart.validateData();
}
#chartdiv {
width: 100%;
height: 500px;
font-family: Verdana;
font-size: 12px;
}
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<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>
<script type="text/javascript" src="https://www.amcharts.com/lib/3/themes/light.js"></script>
<script type="text/javascript" src="https://www.amcharts.com/lib/3/amstock.js"></script>
<input type="text" id="year"><input type="submit" id="submit">
<div id="chartdiv"></div>
I am taking date format as "DD-MM-YYYY".
Why is this error occuring?
The plugin assumes that the dates are already date objects. Since you're using string dates, you need to either convert the dates to date objects prior to adding them to the dataProvider, or update the plugin to convert the string dates to date objects for you.
If you're using a string-based date, you have to set dataDateFormat so the chart knows how to parse your dates correctly. Your string dates in the dataProvider that you're generating in your generateChartData function are actually in "MM-DD-YYYY" format, so you'll want to set dataDateFormat: "MM-DD-YYYY" in the top level of your chart config:
chart = AmCharts.makeChart("chartdiv", {
// ...
"dataDateFormat": "MM-DD-YYYY",
// ...
}
From there, you'll want to update the plugin to check if setFullYear is a function of that data point, and convert it to a date object first before having it set the base year using AmCharts.stringToDate:
AmCharts.addInitHandler(function(chart) {
AmCharts.baseYearInitialize = function(chart) {
for (var x = 0; x < chart.dataSets.length; x++) {
var ds = chart.dataSets[x];
if (ds.baseYear !== undefined) {
for (var i = 0; i < ds.dataProvider.length; i++) {
var dp = ds.dataProvider[i];
// if this is not a date object (i.e. setFullYear is not defined) convert it using AmCharts.stringToDate and your chart's dataDateFormat)
if (!dp[ds.categoryField].setFullYear) {
dp[ds.categoryField] = AmCharts.stringToDate(dp[ds.categoryField], chart.dataDateFormat);
}
dp[ds.categoryField].setFullYear(ds.baseYear);
}
}
}
}
AmCharts.baseYearInitialize(chart);
}, ["stock"]);
I also tweaked your code to check if the input is numeric and a valid array element before adding it to the dataProvider:
var chart;
var SER = [];
//var SER;
first();
function first() {
for (var i = 0; i < 5; i++) {
generateChartData(2000 + i);
}
//SER = JSON.stringify(SER1);
//console.log(SER1);
dd();
}
function generateChartData(year) {
var firstDate = new Date(year, 0, 1);
var temp = [];
for (var i = 0; i < 365; i++) {
var newDate = new Date(firstDate);
newDate.setDate(newDate.getDate() + i);
newDate = ((newDate.getMonth() + 1) < 10 ? "0" + (newDate.getMonth() + 1) : (newDate.getMonth() + 1)) +
"-" + (newDate.getDate() < 10 ? "0" + newDate.getDate() : newDate.getDate()) +
"-" + year;
temp.push({
date: newDate,
value: Math.round(Math.random() * (40 + i)) + 100 + i
});
}
SER.push(temp);
}
function dd() {
AmCharts.addInitHandler(function(chart) {
AmCharts.baseYearInitialize = function(chart) {
for (var x = 0; x < chart.dataSets.length; x++) {
var ds = chart.dataSets[x];
if (ds.baseYear !== undefined) {
for (var i = 0; i < ds.dataProvider.length; i++) {
var dp = ds.dataProvider[i];
// if this is not a date object (i.e. setFullYear is not defined) convert it using AmCharts.stringToDate and your chart's dataDateFormat)
if (!dp[ds.categoryField].setFullYear) {
dp[ds.categoryField] = AmCharts.stringToDate(dp[ds.categoryField], chart.dataDateFormat);
}
dp[ds.categoryField].setFullYear(ds.baseYear);
}
}
}
}
AmCharts.baseYearInitialize(chart);
}, ["stock"]);
chart = AmCharts.makeChart("chartdiv", {
"type": "stock",
"theme": "light",
"dataDateFormat": "MM-DD-YYYY",
"dataSets": [{
"title": "2000",
"fieldMappings": [{
"fromField": "value",
"toField": "value"
}],
"dataProvider": SER[0],
"categoryField": "date"
}
/* keeping more than one dataset showing error
, {
"title": "2001",
"fieldMappings": [{
"fromField": "value",
"toField": "value"
}],
"dataProvider": SER[1],
"categoryField": "date",
"compared": true,
"baseYear": 2000
}, {
"title": "2002",
"fieldMappings": [{
"fromField": "value",
"toField": "value"
}
*/
],
"panels": [{
"title": "Value",
"categoryAxis": {},
"dateFormats": 'DD-MM-YYYY',
"stockGraphs": [{
"id": "g1",
"valueField": "value",
"lineThickness": 2,
"comparable": true,
"compareField": "value",
"balloonText": "[[title]]:<b>[[value]]</b>",
"compareGraphBalloonText": "[[title]]:<b>[[value]]</b>",
"compareGraph": {
"dashLength": 5,
"lineThickness": 2
}
}],
"stockLegend": {
"periodValueTextComparing": "[[percents.value.close]]%",
"periodValueTextRegular": "[[value.close]]"
}
}],
"panelsSettings": {
"recalculateToPercents": "never"
},
"chartScrollbarSettings": {
"graph": "g1"
},
"chartCursorSettings": {
"valueBalloonsEnabled": true,
"fullWidth": true,
"cursorAlpha": 0.1,
"valueLineBalloonEnabled": true,
"valueLineEnabled": true,
"valueLineAlpha": 0.5
},
"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"
}]
}
});
$('document').ready(function() {
$('#submit').on('click', function() {
add(+document.getElementById('year').value);
});
});
}
function add(yr) {
if (!isNaN(yr) && SER[yr - 2000] !== undefined) {
chart.dataSets.push({
"title": yr,
"fieldMappings": [{
"fromField": "value",
"toField": "value"
}],
"dataProvider": SER[yr - 2000],
"categoryField": "date",
"compared": true,
"baseYear": 2000
});
AmCharts.baseYearInitialize(chart);
chart.validateData();
}
}
#chartdiv {
width: 100%;
height: 500px;
font-family: Verdana;
font-size: 12px;
}
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<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>
<script type="text/javascript" src="https://www.amcharts.com/lib/3/themes/light.js"></script>
<script type="text/javascript" src="https://www.amcharts.com/lib/3/amstock.js"></script>
<input type="text" id="year"><input type="submit" id="submit">
<div id="chartdiv"></div>

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

I want to show Diamond Shaped icon in my chart created using amCharts

I want to show diamond-shaped icon in my chart. I have created this charts using amCharts.
My present amChart:
And I want to put diamond-shaped icon just like in following image:
Here is my JavaScript code:
function getChart(id) {
var allCharts = AmCharts.charts;
for (var i = 0; i < allCharts.length; i++) {
if (id == allCharts[i].div.id) {
return allCharts[i];
}
}
}
function load_holding_graph(graph_type, history, title, aggregate, industry){
var title_1 = industry[0].ticker + '\n';
var title_2 = industry[0].name;
var title_3 = industry[0].industry + ' . ' + industry[0].sector;
// current day exclude weekends
var current_date = new Date();
switch(current_date.getDay()){
case 0:
var s = new Date(current_date.getTime());
var d = s.setDate(current_date.getDate() - 1);
break;
case 6:
var s = new Date(current_date.getTime());
var d = s.setDate(current_date.getDate() - 2);
break;
default:
var d = current_date;
}
var latest_trading_day = $.datepicker.formatDate('dd MM, yy', d);
// CREATE DATA
var chartData = [];
generateChartData(history);
function generateChartData() {
for (var i = 0; i < history.length; i++) {
var date = new Date(history[i].date);
var val = Math.round(Math.random() * (30) + 100);
chartData[i] = ({
date: date,
open: history[i].open,
close: history[i].close,
high: history[i].high,
low: history[i].low,
volume: history[i].volume,
value: val
});
}
}
// CHART CONFIG
var chartConfig = {
type: "stock",
pathToImages : "/static/img/amcharts/",
addClassNames:true,
dataSets: [{
fieldMappings: [{
fromField: "open",
toField: "open"
}, {
fromField: "close",
toField: "close"
}, {
fromField: "high",
toField: "high"
}, {
fromField: "low",
toField: "low"
}, {
fromField: "volume",
toField: "volume"
}, {
fromField: "val",
toField: "val"
}
],
color: "#fff",
dataProvider: chartData,
title: title,
categoryField: "date",
compared: false,
},
{
fieldMappings: [{
fromField: "value",
toField: "value"
}],
color: "#fff",
dataProvider: chartData,
title: title,
categoryField: "date"
},
],
panels: [{
addClassNames:true,
percentHeight: 75,
valueAxes: [{
id:"v1",
//logarithmic:true,
unit : '$',
unitPosition:"left",
position:"left",
},
{
id:"v2",
unit : '$',
unitPosition:"left",
position:"right",
synchronizeWith: "v1",
synchronizationMultiplier: 1,
},
],
marginBottom: 0,
marginTop: 0,
stockGraphs: [{type: graph_type,
id: "g1",
title:title,
openField: "open",
closeField: "close",
highField: "high",
lowField: "low",
valueField: "close",
lineColor: "#11EDF1",
fillColors: "#11EDF1",
negativeLineColor: "#db4c3c",
negativeFillColors: "#db4c3c",
fillAlphas: 1,
// comparedGraphLineThickness: 2,
columnWidth: 0.4,
useDataSetColors: false,
comparable: true,
compareField: "close",
bullet : "round",
bulletAlpha : 0,
showBalloon: true,
showBalloonAt:"top",
"balloonText":"$[[value]]",
} ],
stockLegend: {
enabled:true,
useGraphSettings:true,
data:[{title: ""}],
// valueTextRegular: undefined,
periodValueTextComparing: "[[percents.value.close]]%",
markerType: "diamond",
backgroundColor :"#ffffff",
markerSize : 24,
position:"top",
},
},
],
panelsSettings: {
color: "#fff",
plotAreaFillColors: "#333",
plotAreaFillAlphas: 1,
marginLeft: 60,
marginRight: 60,
marginTop: 20,
marginBottom: 5,
},
categoryAxesSettings: {
equalSpacing: true,
gridColor: "#555",
gridAlpha: 1,
maxSeries:0,
markPeriodChange:false,
autoGridCount:true,
minHorizontalGap:100,
dateFormats: [{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, YYYY'},
{period:'WW',format:'MMM DD'},
{period:'MM',format:'MMM YYYY'},
{period:'YYYY',format:'YYYY'}],
},
valueAxesSettings: {
gridColor: "#555",
gridAlpha: 1,
inside: false,
showLastLabel: true,
},
chartCursorSettings: {
pan: true,
valueLineEnabled:true,
valueLineBalloonEnabled:true,
onePanelOnly:true,
},
legendSettings: {
color: "#fff"
},
stockEventsSettings: {
showAt: "high"
},
balloon: {
textAlign: "left",
offsetY: 10,
},
"export": {
"enabled": true,
"backgroundColor": "#fff",
},
}
AmCharts.charts = [];
// CREATE CHART
var chart = AmCharts.makeChart("holding-graph",chartConfig);
console.log(chart)
}
If your chart never uses data point grouping, either by having few data points or having it disabled, you should go with the bulletField solution #gerric proposed.
If the above does not apply, probably the best course of action is to use Trend lines for that.
A trend line is basically a line from one datetime/value pair to another. However, it can also have an icon attached at its either end, which we can exploit to add a diamond image (we're going to use SVG) at any point of the chart.
Here's an example of a ready-made chart:
var icon = "M256,0L96,256l160,256l160-256L256,0z";
var chartData = [];
var iconDate, iconValue;
generateChartData();
function generateChartData() {
var firstDate = new Date();
firstDate.setDate(firstDate.getDate() - 500);
firstDate.setHours(0, 0, 0, 0);
for (var i = 0; i < 500; i++) {
var newDate = new Date(firstDate);
newDate.setDate(newDate.getDate() + i);
var val = Math.round(Math.random() * (40 + i)) + 100 + i;
chartData.push({
date: newDate,
value1: val
});
if (i === 480) {
iconDate = new Date(newDate);
iconDate.setHours(12);
iconValue = val;
}
}
}
var chart = AmCharts.makeChart("chartdiv", {
type: "stock",
"theme": "light",
"dataSets": [{
"fieldMappings": [{
"fromField": "value1",
"toField": "value1"
}, {
"fromField": "value2",
"toField": "value2"
}, {
"fromField": "value3",
"toField": "value3"
}, {
"fromField": "value4",
"toField": "value4"
}],
"dataProvider": chartData,
"categoryField": "date"
}],
"panels": [{
"stockGraphs": [{
"id": "g1",
"title": "Graph #1",
"lineThickness": 2,
"valueField": "value1",
"useDataSetColors": false
}],
"trendLines": [{
"initialValue": iconValue,
"initialDate": iconDate,
"lineAlpha": 1,
"lineColor": "#ff0000",
"initialImage": {
"svgPath": icon,
"color": "#cc0000",
"width": 15,
"height": 25,
"offsetX": -7
},
"finalValue": iconValue,
"finalDate": iconDate
}]
}],
"chartScrollbarSettings": {
"graph": "g1"
},
"chartCursorSettings": {
"valueBalloonsEnabled": true,
"fullWidth": true,
"cursorAlpha": 0.1,
"valueLineBalloonEnabled": true,
"valueLineEnabled": true,
"valueLineAlpha": 0.5
},
"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"
}]
}
});
<script src="http://www.amcharts.com/lib/3/amcharts.js"></script>
<script src="http://www.amcharts.com/lib/3/serial.js"></script>
<script src="http://www.amcharts.com/lib/3/amstock.js"></script>
<div id="chartdiv" style="width: 100%; height: 300px;"></div>
If you use bulletField, you can set bullets from within your data. The diamond shape is already provided by AmCharts.These two examples could help you out: fiddle & amDemo

Categories