Related
I have a function I'm using to add new data points to my stock chart. I need to create a condition under which one of the data points comes with an icon. I see that stockEvents can do this but it's not showing in my chart:
function addDataPoint(ask) {
var dataProvider = chart.dataSets[0].dataProvider;
var newDate = new Date(dataProvider[dataProvider.length - 1].date.getTime());
newDate.setHours(newDate.getHours(), newDate.getMinutes() + 1, newDate.getSeconds());
var a = Math.round(Math.random() * (40 + 1000)) + 100 + 1000;
var b = Math.round(Math.random() * 100000000);
dataProvider.push({
date: newDate,
value: ask,
volume: ask
});
chart.dataSets[0].stockEvents = [{
date: newDate,
type: "flag",
text: "F",
description: "Some longer\ntext can also\n be added"
}];
dataProvider.shift();
}
You need to set the stock event's graph property in order for it to be visible. This can be a reference to the stock graph object, or the graph's id. You also need to call validateData in order to update the chart if you aren't already doing so outside of your addDataPoint function.
AmCharts.makeChart("chartdiv", {
// ...
"panels": [{
// ...
"stockGraphs": [{
// ...
"id": "g1", //added id
// ...
},
// ...
]
},
// ...
],
// ...
});
// ...
function addDataPoint(ask) {
// ...
chart.dataSets[0].stockEvents = [{
date: newDate,
type: "flag",
text: "F",
graph: "g1", //added
description: "Some longer\ntext can also\n be added"
}];
dataProvider.shift();
chart.validateData(); //added
}
Also note that you're overwriting the stockEvents array each time in your addDataPoint function. If you want to preserve your previous event, then you need to use push since it's an array.
Demo
I am using amchart for a graph. Below is the code,
var chart = AmCharts.makeChart("chartdiv", {
"theme": "light",
"type": "serial",
"startDuration": 2,
"dataProvider": [{
"country": "This is Sample Data with long label",
"visits": 4025,
"color": "#FF0F00"
}, {
"country": "This is Sample Data with long label1",
"visits": 1882,
"color": "#FF6600"
}, {
"country": "This is Sample Data with long label2",
"visits": 1809,
"color": "#FF9E01"
}, {
"country": "This is Sample Data with long label3",
"visits": 1322,
"color": "#FCD202"
}, {
"country": "This is Sample Data with long label4",
"visits": 1122,
"color": "#F8FF01"
}, {
"country": "This is Sample Data with long label5",
"visits": 1114,
"color": "#B0DE09"
}, {
"country": "This is Sample Data with long label6",
"visits": 984,
"color": "#04D215"
}, {
"country": "This is Sample Data with long label7",
"visits": 711,
"color": "#0D8ECF"
}, {
"country": "This is Sample Data with long label8",
"visits": 665,
"color": "#0D52D1"
}, {
"country": "This is Sample Data with long label9",
"visits": 580,
"color": "#2A0CD0"
}, {
"country": "This is Sample Data with long label10",
"visits": 443,
"color": "#8A0CCF"
}, {
"country": "This is Sample Data with long label11",
"visits": 441,
"color": "#CD0D74"
}, {
"country": "This is Sample Data with long label12",
"visits": 395,
"color": "#754DEB"
}, {
"country": "This is Sample Data with long label13",
"visits": 386,
"color": "#DDDDDD"
}, {
"country": "This is Sample Data with long label14",
"visits": 338,
"color": "#333333"
}],
"valueAxes": [{
"position": "left",
"axisAlpha":0,
"gridAlpha":0
}],
"graphs": [{
"balloonText": "[[category]]: <b>[[value]]</b>",
"colorField": "color",
"fillAlphas": 0.85,
"lineAlpha": 0.1,
"type": "column",
"topRadius":1,
"valueField": "visits"
}],
"depth3D": 40,
"angle": 30,
"chartCursor": {
"categoryBalloonEnabled": false,
"cursorAlpha": 0,
"zoomable": false
},
"categoryField": "country",
"categoryAxis": {
"gridPosition": "start",
"axisAlpha":0,
"gridAlpha":0
},
"labelFunction": function(label, item, axis) {
var chart = axis.chart;
if ( (chart.realWidth <= 300 ) && ( label.length > 5 ) )
return label.substr(0, 5) + '...';
if ( (chart.realWidth <= 500 ) && ( label.length > 10 ) )
return label.substr(0, 10) + '...';
return label;
},
"legend": {
"useGraphSettings": true
},
"export": {
"enabled": true
}
}, 0);
However the Xaxis label is very lenghy, I wanted to auto truncate the long category axis labels like this example and also enable legend. But enabling legend doesn't work, also auto truncating doesn't seem to work. Could someone help me out here? Thanks in advance.
Here is the link to codepen [1].
[1] https://codepen.io/gknathkumar/pen/OxKGev
As others have stated, the labelFunction is part of the categoryAxis, so it needs to go in there. I'm partial to the method in kuzyn's implementation, but pick whichever you want.
As for the legend, it is generated by graph objects by design. Since there's one graph object, there's only one marker. Adding a marker for each column requires you add custom code that modifies the legend's data array to generate customized markers. AmCharts has a knowledge base article for generating markers for each column. Relevant code below:
/*
Plugin to generate legend markers based on category
and fillColor/lineColor/color field from the chart data by using
the legend's custom data array. Also allows for toggling markers
by completely removing/adding columns from the chart
The plugin assumes there is only one graph object.
*/
AmCharts.addInitHandler(function(chart) {
//method to handle removing/adding columns when the marker is toggled
function handleCustomMarkerToggle(legendEvent) {
var dataProvider = legendEvent.chart.dataProvider;
var itemIndex; //store the location of the removed item
//Set a custom flag so that the dataUpdated event doesn't fire infinitely, in case you have
//a dataUpdated event of your own
legendEvent.chart.toggleLegend = true;
// The following toggles the markers on and off.
// The only way to "hide" a column and reserved space on the axis is to remove it
// completely from the dataProvider. You'll want to use the hidden flag as a means
// to store/retrieve the object as needed and then sort it back to its original location
// on the chart using the dataIdx property in the init handler
if (undefined !== legendEvent.dataItem.hidden && legendEvent.dataItem.hidden) {
legendEvent.dataItem.hidden = false;
dataProvider.push(legendEvent.dataItem.storedObj);
legendEvent.dataItem.storedObj = undefined;
//re-sort the array by dataIdx so it comes back in the right order.
dataProvider.sort(function(lhs, rhs) {
return lhs.dataIdx - rhs.dataIdx;
});
} else {
// toggle the marker off
legendEvent.dataItem.hidden = true;
//get the index of the data item from the data provider, using the
//dataIdx property.
for (var i = 0; i < dataProvider.length; ++i) {
if (dataProvider[i].dataIdx === legendEvent.dataItem.dataIdx) {
itemIndex = i;
break;
}
}
//store the object into the dataItem
legendEvent.dataItem.storedObj = dataProvider[itemIndex];
//remove it
dataProvider.splice(itemIndex, 1);
}
legendEvent.chart.validateData(); //redraw the chart
}
//check if legend is enabled and custom generateFromData property
//is set before running
if (!chart.legend || !chart.legend.enabled || !chart.legend.generateFromData) {
return;
}
var categoryField = chart.categoryField;
var colorField = chart.graphs[0].lineColorField || chart.graphs[0].fillColorsField || chart.graphs[0].colorField;
var legendData = chart.dataProvider.map(function(data, idx) {
var markerData = {
"title": data[categoryField] + ": " + data[chart.graphs[0].valueField],
"color": data[colorField],
"dataIdx": idx //store a copy of the index of where this appears in the dataProvider array for ease of removal/re-insertion
};
if (!markerData.color) {
markerData.color = chart.graphs[0].lineColor;
}
data.dataIdx = idx; //also store it in the dataProvider object itself
return markerData;
});
chart.legend.data = legendData;
//make the markers toggleable
chart.legend.switchable = true;
chart.legend.addListener("clickMarker", handleCustomMarkerToggle);
}, ["serial"]);
This plugin requires that you set a custom generateFromData flag to true in your legend and nothing else (useGraphSettings is not compatible):
"legend": {
"generateFromData": true //custom property for the plugin
},
Here's a demo that leverages kuzyn's trim method and the aforementioned plugin:
/*
Plugin to generate legend markers based on category
and fillColor/lineColor/color field from the chart data by using
the legend's custom data array. Also allows for toggling markers
by completely removing/adding columns from the chart
The plugin assumes there is only one graph object.
*/
AmCharts.addInitHandler(function(chart) {
//method to handle removing/adding columns when the marker is toggled
function handleCustomMarkerToggle(legendEvent) {
var dataProvider = legendEvent.chart.dataProvider;
var itemIndex; //store the location of the removed item
//Set a custom flag so that the dataUpdated event doesn't fire infinitely, in case you have
//a dataUpdated event of your own
legendEvent.chart.toggleLegend = true;
// The following toggles the markers on and off.
// The only way to "hide" a column and reserved space on the axis is to remove it
// completely from the dataProvider. You'll want to use the hidden flag as a means
// to store/retrieve the object as needed and then sort it back to its original location
// on the chart using the dataIdx property in the init handler
if (undefined !== legendEvent.dataItem.hidden && legendEvent.dataItem.hidden) {
legendEvent.dataItem.hidden = false;
dataProvider.push(legendEvent.dataItem.storedObj);
legendEvent.dataItem.storedObj = undefined;
//re-sort the array by dataIdx so it comes back in the right order.
dataProvider.sort(function(lhs, rhs) {
return lhs.dataIdx - rhs.dataIdx;
});
} else {
// toggle the marker off
legendEvent.dataItem.hidden = true;
//get the index of the data item from the data provider, using the
//dataIdx property.
for (var i = 0; i < dataProvider.length; ++i) {
if (dataProvider[i].dataIdx === legendEvent.dataItem.dataIdx) {
itemIndex = i;
break;
}
}
//store the object into the dataItem
legendEvent.dataItem.storedObj = dataProvider[itemIndex];
//remove it
dataProvider.splice(itemIndex, 1);
}
legendEvent.chart.validateData(); //redraw the chart
}
//check if legend is enabled and custom generateFromData property
//is set before running
if (!chart.legend || !chart.legend.enabled || !chart.legend.generateFromData) {
return;
}
var categoryField = chart.categoryField;
var colorField = chart.graphs[0].lineColorField || chart.graphs[0].fillColorsField || chart.graphs[0].colorField;
var legendData = chart.dataProvider.map(function(data, idx) {
var markerData = {
"title": data[categoryField] + ": " + data[chart.graphs[0].valueField],
"color": data[colorField],
"dataIdx": idx //store a copy of the index of where this appears in the dataProvider array for ease of removal/re-insertion
};
if (!markerData.color) {
markerData.color = chart.graphs[0].lineColor;
}
data.dataIdx = idx; //also store it in the dataProvider object itself
return markerData;
});
chart.legend.data = legendData;
//make the markers toggleable
chart.legend.switchable = true;
chart.legend.addListener("clickMarker", handleCustomMarkerToggle);
}, ["serial"]);
// keep the data object separate from the call
var dataProvider = [
{
country: "This is Sample Data with long label",
visits: 4025,
color: "#FF0F00"
},
{
country: "This is Sample Data with long label1",
visits: 1882,
color: "#FF6600"
},
{
country: "This is Sample Data with long label2",
visits: 1809,
color: "#FF9E01"
},
{
country: "This is Sample Data with long label3",
visits: 1322,
color: "#FCD202"
}
];
var chart = AmCharts.makeChart(
"chartdiv",
{
theme: "light",
type: "serial",
startDuration: 2,
dataProvider: dataProvider,
valueAxes: [
{
position: "left",
axisAlpha: 0,
gridAlpha: 0
}
],
graphs: [
{
balloonText: "[[category]]: <b>[[value]]</b>",
colorField: "color",
fillAlphas: 0.85,
lineAlpha: 0.1,
type: "column",
topRadius: 1,
valueField: "visits"
}
],
depth3D: 40,
angle: 30,
chartCursor: {
categoryBalloonEnabled: false,
cursorAlpha: 0,
zoomable: false
},
categoryField: "country",
categoryAxis: {
gridPosition: "start",
axisAlpha: 0,
gridAlpha: 0,
labelFunction: trimLabel,
},
legend: {
generateFromData: true //custom property for the plugin
},
export: {
enabled: true
}
},
0
);
// function to trim the labels
function trimLabel(label, item, axis) {
var chartWidth = axis.chart.realWidth;
var maxLabelLength = 15; // not counting the dots...
// trim when the width of the chart is smalled than 300px
if (chartWidth <= 300 && label.length > 5)
return label.substr(0, 5) + "...";
// trim when the width of the chart is smalled than 500px
if (chartWidth <= 500 && label.length > 10)
return label.substr(0, 10) + "...";
// trim when label is longer than maxLabelLength regardless of chart width
return label.length >= 15 ? label.substr(0, 14) + "...": label;
}
#chartdiv {
width: 990px;
height: 365px;
border-radius: 3px;
margin: 0px;
border: 1px dotted #728FCE;
}
<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/themes/light.js"></script>
<input type="button" value="Set width to 300px" onclick="document.getElementById('chartdiv').style.width='300px';" />
<input type="button" value="Set width to 500px" onclick="document.getElementById('chartdiv').style.width='500px';" />
<input type="button" value="Set width to 700px" onclick="document.getElementById('chartdiv').style.width='700px';" />
<div id="chartdiv"></div>
Note that if you want the labels on the markers trimmed, you'll have to call trim when creating the markers' titles in the initHandler as well.
make labelFunction like below:
"labelFunction": function(label, item, axis) {
var chart = axis.chart;
console.log("CHART:", chart.realWidth, label.length, label );
if ( ( label.length > 5 ) ){
console.log("CHARTLABEL:", label.substr(0, 5) + '...');
return label.substr(0, 7) + '...';
}
if ( ( label.length > 10 ) ){
return label.substr(0, 10) + '...';
}
return label;
},
And your code was not working because you have to put label function inside categoryAxis
Final working solution : https://codepen.io/anon/pen/aLerBZ?editors=0010
There are a couple of small mistake in your code:
labelFunction is not in categoryAxis
the size of your chart never drops below 500px, hence the labels were never trimmed like in the example
some of the code could have been put in variables to make is easier to debug
I've separated some of the code, and added a maximum length (15 characters) for labels regardless of the chart width
View the full example on Codepen
// keep the data object separate from the call
var dataProvider = [
{
country: "This is Sample Data with long label",
visits: 4025,
color: "#FF0F00"
},
{
country: "This is Sample Data with long label1",
visits: 1882,
color: "#FF6600"
},
{
country: "This is Sample Data with long label2",
visits: 1809,
color: "#FF9E01"
},
{
country: "This is Sample Data with long label3",
visits: 1322,
color: "#FCD202"
}
];
var chart = AmCharts.makeChart(
"chartdiv",
{
theme: "light",
type: "serial",
startDuration: 2,
dataProvider: dataProvider,
valueAxes: [
{
position: "left",
axisAlpha: 0,
gridAlpha: 0
}
],
graphs: [
{
balloonText: "[[category]]: <b>[[value]]</b>",
colorField: "color",
fillAlphas: 0.85,
lineAlpha: 0.1,
type: "column",
topRadius: 1,
valueField: "visits"
}
],
depth3D: 40,
angle: 30,
chartCursor: {
categoryBalloonEnabled: false,
cursorAlpha: 0,
zoomable: false
},
categoryField: "country",
categoryAxis: {
gridPosition: "start",
axisAlpha: 0,
gridAlpha: 0,
labelFunction: trimLabel,
},
legend: {
useGraphSettings: true
},
export: {
enabled: true
}
},
0
);
// function to trim the labels
function trimLabel(label, item, axis) {
var chartWidth = axis.chart.realWidth;
var maxLabelLength = 15; // not counting the dots...
// trim when the width of the chart is smalled than 300px
if (chartWidth <= 300 && label.length > 5)
return label.substr(0, 5) + "...";
// trim when the width of the chart is smalled than 500px
if (chartWidth <= 500 && label.length > 10)
return label.substr(0, 10) + "...";
// trim when label is longer than maxLabelLength regardless of chart width
return label.length >= 15 ? label.substr(0, 14) + "...": label;
}
I have a simple Highcharts pie chart that takes the following data as input:
data: [
{"y":4, "name":"Russia", "txt": "Our hotel at the countryside was very nice and welcoming."},
{"y":2, "name":"Australia", "txt": "The trip to Ayers Rock was one of the highlights of our trip. The Great Barrier Reef and its clear water were simply amazing!"},
{"y":1, "name":"Argentina", "txt": "It has been a childhood dream to just go into the wild."},
{"y":4, "name":"China", "txt": "in year 1930 it was this is just a silly simple text to check if everything here is working."},
{"y":2, "name":"Neverland", "txt": "in year 1940 it was like this."},
{"y":4, "name":"Mars", "txt": "in year 1900 it was like this."}
]
Example:
$(document).ready(function() {
//var colors = ['#8d62a0', '#ceb3d8', '#d5dddd'];
Highcharts.getOptions().plotOptions.pie.colors = (function () {
var colors = [],
base = '#801a00',
i;
for (i = 0; i < 100; i += 1) {
colors.push(Highcharts.Color(base).brighten((i - 3) / 15).get());
}
return colors;
}());
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'pie'
},
tooltip: {
formatter: function() {
return '<b>'+this.point.name+'</b>';
}
},
legend: {
enabled: false
},
plotOptions: {
pie: {
innerSize: '75%'
},
series: {
cursor: 'pointer',
point: {
events: {
click: function(){
defineInnerData(this.y, this.txt, this);
},
}
},
states: {
hover: {
enabled: false
}
}
}
},
yAxis: {
title: {
text: null
},
labels: {
enabled: false
}
},
series: [{
dataLabels: {
enabled: false
},
data: [
{"y":4, "name":"Russia", "txt": "Our hotel at the countryside was very nice and welcoming."},
{"y":2, "name":"Australia", "txt": "The trip to Ayers Rock was one of the highlights of our trip. The Great Barrier Reef and its clear water were simply amazing!"},
{"y":1, "name":"Argentina", "txt": "It has been a childhood dream to just go into the wild."},
{"y":4, "name":"China", "txt": "in year 1930 it was this is just a silly simple text to check if everything here is working."},
{"y":2, "name":"Neverland", "txt": "in year 1940 it was like this."},
{"y":4, "name":"Mars", "txt": "in year 1900 it was like this."}
]
}]
});
function defineInnerData(name, y, obj) { // on complete
var chart=$("#container").highcharts();
$( "#pieChartInfoText" ).remove();
var textX = chart.plotLeft + (chart.plotWidth * 0.5);
var textY = chart.plotTop + (chart.plotHeight * 0.5);
var span = '<span id="pieChartInfoText" style="position:absolute; text-align:block;left: 235px;top:210px;width: 150px; height: 180px; overflow: scroll;">';
span += '<span style="font-size: 11px">'+ y +'</span><br>';
span += '</span>';
$("#addText").append(span);
span = $('#pieChartInfoText');
span.css('left', textX + (span.width() * -0.5));
span.css('top', textY + (span.height() * -0.5));
span.css('overflow', 'auto');
}
defineInnerData("", "Click on the slices to see the text");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
<script src="http://code.highcharts.com/highcharts.js"></script>
</head>
<body>
<div>
<div id="container" style="position:absolute; left:0px; top:0px;"></div>
<div id="addText" style="position:absolute; left:0px; top:0px;"></div>
</div>
<script src="testfile_highcharts.js"></script>
</body>
</html>
My question now is: How would I read data as input that comes in a different structure like the json code below (its geoJSON), where I would like to get the following values as input for my chart:
The tooltip should show the name of the country (which corresponds to properties.name in the geoJSON).
The number of slices corresponds to the value of data.features.articles (which in turn corresponds to the number of sentences in data.features.text).
When clicking on a slice the corresponding sentence (from data.features.text) should be displayed in the center of the circle.
Here is how the geoJSON data looks like:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"id": 4,
"properties": {
"id": 4,
"name": "Thailand",
"lat": "13.7538929",
"lon": "100.8160803",
"2005": 14
},
"geometry": {
"type": "Point",
"coordinates": [
"100.8160803",
"13.7538929"
]
},
"text": ["The official reason given was that he wanted to give the Thai people time to mourn his father before he became king.", "Thailand has rarely had what might be called routine royal successions. The last was 70 years ago, when the young King Ananda was found shot dead in his bedroom in still unexplained circumstances."],
"sentences": "2"
},
{
"type": "Feature",
"id": 7,
"properties": {
"id": 7,
"name": "the United States",
"lat": "38.8949549",
"lon": "-77.0366455",
"2005": 14
},
"geometry": {
"type": "Point",
"coordinates": [
"-77.0366455",
"38.8949549"
]
},
"text": ["The presidential elections will be a hard fight this year", "The best travelling season is September until end of October", "New York City is a must-see when travelling on the East Coast."],
"sentences": "3"
},
{
"type": "Feature",
"id": 8,
"properties": {
"id": 8,
"name": "Greece",
"lat": "37.9841493",
"lon": "23.7279843",
"2005": 14
},
"geometry": {
"type": "Point",
"coordinates": [
"23.7279843",
"37.9841493"
]
},
"text": ["The Aegean islands are little paradise spots not far away from the bustling capital Athens "],
"sentences": "1"
}
]
}
I've tried for hours now to get this working, but I cannot seem to be able to do it. I'm very new to JavaScript and would appreciate every help here. I'm also sorry if the explanation of my problems should not be entirely clear, but I hope that there is someone who can still help me...
The key point to accomplish this is to convert the json structured data to a javascript object in the strucuture you want.
For do this you should iterate over the json object, get the values you want and exports it to the list you're passing to chart.
// The empty list passed to chart
var dataToChart = [];
// Empty object of the list
var dataToChartObject = {"y":0, "name":"", "txt": ""}
// Iterate over jSon to populate dataToChartObject
$.each(jsonObject.features, function(index, value){
dataToChartObject.name = value.properties.name;
dataToChartObject.txt = value.text[0]
// I didn't realize what the articles number is, but do the same logic to get it
// Now let's insert the object to the list
dataToChart.push(dataToChartObject);
});
This can be done in by traversing the JSON object by its properties:
var featureSet = theJSON.features;
var theData = [];
for (var item in featureSet) {
var set = featureSet[item];
for (var theText in set.text) {
var theSlice = {};
theSlice.name = set.properties.name;
theSlice.y = set.text.length;
theSlice.txt = set.text[theText];
theData.push(theSlice);
}
}
Where theJSON is your returned JSON object. From here you modify the chart to use theData.
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'pie'
},
tooltip: {
formatter: function() {
return '<b>'+this.point.name+'</b>';
}
},
legend: {
enabled: false
},
plotOptions: {
pie: {
innerSize: '75%'
},
series: {
cursor: 'pointer',
point: {
events: {
click: function(){
defineInnerData(this.y, this.txt, this);
},
}
},
states: {
hover: {
enabled: false
}
}
}
},
yAxis: {
title: {
text: null
},
labels: {
enabled: false
}
},
series: [{
dataLabels: {
enabled: false
},
data: theData
}]
});
Sample jsFiddle. Note that your selector on which slice to pick is not happy due to multiple same name/value slices. I would add an index value to each slice and key off of that instead.
I'm trying to add cities on a county map. The lat and long are drawn corectcly on the full size map(Romania level) but on the county map these are drawn wrong. I think I should rescale the map or lat/long of the city, I don't know...
How should I generate the county map in accordance with cities lat/long?
The code is listed below:
http://jsfiddle.net/xzAx7/33/
var map;
AmCharts.ready(function() {
map = new AmCharts.AmMap();
map.pathToImages = "http://www.ammap.com/lib/images/";
//map.panEventsEnabled = true; // this line enables pinch-zooming and dragging on touch devices
map.balloon.color = "#000000";
var wordlDataProvider = {
mapVar: AmCharts.maps.Cluj,
getAreasFromMap: true,
areas: [
{ id: "FR", color: "#4444ff" },
{ id: "RU", color: "#4444ff" },
{ id: "US", color: "#4444ff" }
],
images: [{
title: "ClujNapoca",
latitude: 46.85307355,
longitude: 23.63327696,
type: "circle",
color: "red",
scale: 0.5
}, {
title: "Turda",
latitude: 46.5745618,
longitude: 23.78573862,
type: "circle",
color: "red",
scale: 0.5
}]
};
map.dataProvider = wordlDataProvider;
map.areasSettings = {
autoZoom: true,
selectedColor: "#CC0000"
};
map.write("mapdiv");
});
I've found the solution. You need to define "defs" properties (leftLongiitude, ...) when you create a custom map. This is specified in this article - https://www.amcharts.com/tutorials/creating-custom-maps-for-javascript-ammap/
In the amCharts article is explained how you can get these "defs" properties.
I've changes the code below to understand how it works
"defs": {
"amcharts:ammap": {
"projection":"mercator",
"leftLongitude":"22.607117",
"topLatitude":"47.363798",
"rightLongitude":"24.261932",
"bottomLatitude":"46.384241"
}
}
demo: http://jsfiddle.net/xzAx7/35/
I need to create a multi leveled that is dynamic because I have to drill down to hundreds or even thousands of data providers that will load from the database. The flow goes like this: I have 1, 2, 3, 4, and 5 years that will drill down to 16 Departments each and will drill down to Courses 10 or more courses. Doing it manually is tedious and I need it to be dynamic. Please help me.
The variables:
var ccs_final_data = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/final_ccs_data");
//VAR CCS AVERAGE_FINAL
var drill_down_to_ccs_courses_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_courses_data_average_final");
var drill_down_to_ccs_sections_BSIT_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_sections_data_BSIT_average_final");
var drill_down_to_ccs_sections_ACT_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_sections_data_ACT_average_final");
var drill_down_to_ccs_sections_BSCS_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_sections_data_BSCS_average_final");
The graph:
var chart2 = AmCharts.makeChart( "ccs2", {
"theme": "light",
type: "serial",
pathToImages: "http://cdn.amcharts.com/lib/3/images/",
dataProvider: ccs_final_data,
categoryField: "category",
categoryAxis: {
labelRotation: 0,
gridPosition: "start"
},
valueAxes: [ {
title: "CCS FINAL TERM - Passing"
} ],
graphs: [ {
valueField: "value",
colorField: "color",
type: "column",
lineAlpha: 100,
fillAlphas: 1
} ],
chartScrollbar: {
"updateOnReleaseOnly": true
},
chartCursor: {
bulletsEnabled: "enabled",
bulletSize: 15,
cursorAlpha: 100,
cursorColor: "#CC0000",
zoomable: true,
categoryBalloonEnabled: true
},
export: {
enabled: true
}
} );
Here's the drill down stuff:
chart2.addListener("clickGraphItem", function (event) {
if(event.item.category == "Average"){
event.chart.dataProvider = drill_down_to_ccs_courses_average_final;
event.chart.validateData();
chart2.addListener("clickGraphItem", function (event) {
if(event.item.category == "BSIT"){
event.chart.dataProvider = drill_down_to_ccs_sections_BSIT_average_final;
event.chart.validateData();
}
else if(event.item.category == "ACT"){
event.chart.dataProvider = drill_down_to_ccs_sections_ACT_average_final;
event.chart.validateData();
}
else if(event.item.category == "BSCS"){
event.chart.dataProvider = drill_down_to_ccs_sections_BSCS_average_final;
event.chart.validateData();
}
});
}
I'd say the best way to make it dynamic is to include some custom field for each data point in your data that would be passed in to server-side script so it knows which data to load.
I'm assuming your data looks like this now:
[ {
"category": "BSIT",
"value": 100
}, {
"category": "ACT",
"value": 200
}, {
"category": "BSCS",
"value": 150
} ]
You could easily add a third field to hold the information for drill-down data load:
[ {
"category": "BSIT",
"value": 100,
"drill": "ccs_sections_data_BSIT_average_final"
}, {
"category": "ACT",
"value": 200,
"drill": "ccs_sections_data_ACT_average_final"
}, {
"category": "BSCS",
"value": 150,
"drill": "ccs_sections_data_BSCS_average_final"
} ]
Then, when clickGraphItem event occurs, you could just take that info and pass it to load script dynamically:
chart2.addListener( "clickGraphItem", function( event ) {
if ( event.item.dataContext.drill !== undefined ) {
event.chart.dataProvider = AmCharts.loadJSON( "<?php echo base_url();?>index.php/osa/" + event.item.dataContext.drill );
event.chart.validateData();
}
} );
This way, you could have any number of drill-down levels, with each level data containing info about where to look for the data for the next level.
Also, I'm not sure as you haven't posted the code for it, so I'm assuming that AmCharts.loadJSON method is synchronous. If it's not (for example if you are using method from Data Loader), you will need to assign the chart's dataProvider after the data is loaded.