How to download multiple am4charts with layout in one PDF file? - amcharts

I want to export multiple am4charts with layout in one PDF like it was in V3
https://www.amcharts.com/docs/v3/tutorials/exporting-pdf-with-multiple-charts-and-related-info/

Please follow the new tutorial how to generate a multi-content PDF.
You can add another chart as extraSprites from version 4.2.0 as in:
chart.exporting.extraSprites.push(chart2);
Check more about how to add an extra element here.
Previous Recommendation
I recommend you to check the answer for this issue: https://github.com/amcharts/amcharts4/issues/743
amCharts uses PDFMake to generate PDFs, which allows you to assemble PDF as you whish.
Please check a simpler example how your code could look like:
// Use this method to call the export functionality
let exportCharts = async (charts) => {
// Map chats to images
let images = await Promise.all(charts.map(async (chart) => {
return await new Promise((resolve, reject) => {
let getImage = () => {
resolve(chart.exporting.getImage('png'));
}
// Get the image if the chart is ready
if (chart.isReady())
getImage();
// Get the image when the chart is ready
else
chart.events.on('ready', () => getImage());
});
}));
// Begin PDF layout
const layout = {
content: []
};
// Add charts
layout.content = images.map((image) => {
return {
image: image,
fit: [523, 300]
};
});
// Finally, download our PDF
charts[0].exporting.pdfmake.then(function(pdfMake) {
pdfMake.createPdf(layout).download("amcharts4.pdf");
});
}
// Call exports with all the charts you want exported
exportCharts([chart1, chart2]);
/**
* ---------------------------------------
* This demo was created using amCharts 4.
*
* For more information visit:
* https://www.amcharts.com/
*
* Documentation is available at:
* https://www.amcharts.com/docs/v4/
* ---------------------------------------
*/
// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end
// Create chart instance
var chart1 = am4core.create('chart-1', am4charts.XYChart3D);
// Add data
chart1.data = [{
"country": "USA",
"visits": 4025
}, {
"country": "China",
"visits": 1882
}, {
"country": "Japan",
"visits": 1809
}, {
"country": "Germany",
"visits": 1322
}, {
"country": "UK",
"visits": 1122
}, {
"country": "France",
"visits": 1114
}, {
"country": "India",
"visits": 984
}, {
"country": "Spain",
"visits": 711
}, {
"country": "Netherlands",
"visits": 665
}, {
"country": "Russia",
"visits": 580
}, {
"country": "South Korea",
"visits": 443
}, {
"country": "Canada",
"visits": 441
}, {
"country": "Brazil",
"visits": 395
}, {
"country": "Italy",
"visits": 386
}, {
"country": "Australia",
"visits": 384
}, {
"country": "Taiwan",
"visits": 338
}, {
"country": "Poland",
"visits": 328
}];
// Create axes
let categoryAxis = chart1.xAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "country";
categoryAxis.renderer.labels.template.rotation = 270;
categoryAxis.renderer.labels.template.hideOversized = false;
categoryAxis.renderer.minGridDistance = 20;
categoryAxis.renderer.labels.template.horizontalCenter = "right";
categoryAxis.renderer.labels.template.verticalCenter = "middle";
categoryAxis.tooltip.label.rotation = 270;
categoryAxis.tooltip.label.horizontalCenter = "right";
categoryAxis.tooltip.label.verticalCenter = "middle";
let valueAxis = chart1.yAxes.push(new am4charts.ValueAxis());
valueAxis.title.text = "Countries";
valueAxis.title.fontWeight = "bold";
// Create series
var series = chart1.series.push(new am4charts.ColumnSeries3D());
series.dataFields.valueY = "visits";
series.dataFields.categoryX = "country";
series.name = "Visits";
series.tooltipText = "{categoryX}: [bold]{valueY}[/]";
series.columns.template.fillOpacity = .8;
var columnTemplate = series.columns.template;
columnTemplate.strokeWidth = 2;
columnTemplate.strokeOpacity = 1;
columnTemplate.stroke = am4core.color("#FFFFFF");
columnTemplate.adapter.add("fill", (fill, target) => {
return chart1.colors.getIndex(target.dataItem.index);
})
columnTemplate.adapter.add("stroke", (stroke, target) => {
return chart1.colors.getIndex(target.dataItem.index);
})
chart1.cursor = new am4charts.XYCursor();
chart1.cursor.lineX.strokeOpacity = 0;
chart1.cursor.lineY.strokeOpacity = 0;
// Create chart instance
var chart2 = am4core.create('chart-2', am4charts.PieChart);
// Add data
chart2.data = [ {
"country": "Lithuania",
"litres": 501.9
}, {
"country": "Czech Republic",
"litres": 301.9
}, {
"country": "Ireland",
"litres": 201.1
}, {
"country": "Germany",
"litres": 165.8
}, {
"country": "Australia",
"litres": 139.9
}, {
"country": "Austria",
"litres": 128.3
}, {
"country": "UK",
"litres": 99
}, {
"country": "Belgium",
"litres": 60
}, {
"country": "The Netherlands",
"litres": 50
} ];
// Add and configure Series
var pieSeries = chart2.series.push(new am4charts.PieSeries());
pieSeries.dataFields.value = "litres";
pieSeries.dataFields.category = "country";
pieSeries.slices.template.stroke = am4core.color("#fff");
pieSeries.slices.template.strokeWidth = 2;
pieSeries.slices.template.strokeOpacity = 1;
// This creates initial animation
pieSeries.hiddenState.properties.opacity = 1;
pieSeries.hiddenState.properties.endAngle = -90;
pieSeries.hiddenState.properties.startAngle = -90;
// Disable labels
pieSeries.labels.template.disabled = true;
pieSeries.ticks.template.disabled = true;
// Use this method to call the export functionality
let exportCharts = async (charts) => {
// Map chats to images
let images = await Promise.all(charts.map(async (chart) => {
return await new Promise((resolve, reject) => {
let getImage = () => {
resolve(chart.exporting.getImage('png'));
}
// Get the image if the chart is ready
if (chart.isReady())
getImage();
// Get the image when the chart is ready
else
chart.events.on('ready', () => getImage());
});
}));
// Begin PDF layout
const layout = {
content: []
};
// Add charts
layout.content = images.map((image) => {
return {
image: image,
fit: [523, 300]
};
});
// Finally, download our PDF
charts[0].exporting.pdfmake.then(function(pdfMake) {
pdfMake.createPdf(layout).download("amcharts4.pdf");
});
}
document.getElementById('print-to-pdf').addEventListener('click', () => {
// Call exports with all the charts you want exported
exportCharts([chart1, chart2]);
});
.ui.segment {
padding: 0;
}
body > .ui.container {
margin-top: 3em;
margin-bottom: 4em;
}
body > .ui.container > .ui.segment {
height: 36em;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css" rel="stylesheet"/>
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<script src="https://www.amcharts.com/lib/4/themes/animated.js"></script>
<script src="https://cdn.jsdelivr.net/npm/viewport-action#0.2.1/dist/viewportAction.min.js"></script>
<div class="ui container">
<button id="print-to-pdf" class="ui blue button">Print</button>
<div id="chart-1" class="ui segment">
<div class="ui active loader"></div>
</div>
<div id="chart-2" class="ui segment">
<div class="ui active loader"></div>
</div>
</div>

Related

How to create smoothed line instead of sharp line in amcharts 4?

unable to smooth line
I've tried to set tensionX, tensionY, chart.smoothing. However, the line is still not smoothed
Here is the jsfiddle filehttps://jsfiddle.net/cherrykosasih02/wyac0dnq/2/
You cannot use tensionX, tensionY or smoothing with propertyFields. You have to create axis ranges instead. Take a look at the following issue on GitHub:
The smoothed curve algorithm works by bending the path around multiple points.
Now, when you are using propertyFields to color specific section of the line, it creates a separate path for each separately-colored segment. If that segment encompasses only two points, the smoothing algorithm does not have anything to work with, hence the straight line.
If you remove series.propertyFields.stroke = "color"; and replace it with series.smoothing = "monotoneX";, you could do something like this:
function colorize(startDate, endDate, color) {
var range = dateAxis.createSeriesRange(series);
range.date = new Date(startDate + ' 12:00');
range.endDate = new Date(endDate + ' 12:00');
range.contents.stroke = am4core.color(color);
}
for (var i = 0; i < chart.data.length; i++) {
var startDate = chart.data[i].date,
endDate = (i < chart.data.length - 1) && chart.data[i + 1].date,
color = chart.data[i].color;
colorize(startDate, endDate, color);
}
Here is your code with these modifications and additions:
/**
* ---------------------------------------
* This demo was created using amCharts 4.
*
* For more information visit:
* https://www.amcharts.com/
*
* Documentation is available at:
* https://www.amcharts.com/docs/v4/
* ---------------------------------------
*/
// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end
// Create chart instance
var chart = am4core.create("chartdiv", am4charts.XYChart);
// Add data
chart.data = [{
"date": "2012-03-01",
"price": 20,
"color": "#00FF00"
}, {
"date": "2012-03-02",
"price": 75,
"color": "#FF0000"
}, {
"date": "2012-03-03",
"price": 15,
"color": "#00FF00"
}, {
"date": "2012-03-04",
"price": 75,
"color": "#00FF00"
}, {
"date": "2012-03-05",
"price": 158,
"color": "#FF0000"
}, {
"date": "2012-03-06",
"price": 57,
"color": "#FF0000"
}, {
"date": "2012-03-07",
"price": 107,
"color": "#FF0000"
}, {
"date": "2012-03-08",
"price": 89,
"color": "#FF0000"
}, {
"date": "2012-03-09",
"price": 75,
"color": "#00FF00"
}, {
"date": "2012-03-10",
"price": 132,
"color": "#00FF00"
}, {
"date": "2012-03-11",
"price": 380,
"color": "#FF0000"
}, {
"date": "2012-03-12",
"price": 56,
"color": "#00FF00"
}, {
"date": "2012-03-13",
"price": 169,
"color": "#FF0000"
}, {
"date": "2012-03-14",
"price": 24,
"color": "#00FF00"
}, {
"date": "2012-03-15",
"price": 147,
"color": "#00FF00"
}];
// Create axes
var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
dateAxis.renderer.grid.template.location = 0;
dateAxis.renderer.minGridDistance = 50;
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
/* valueAxis.logarithmic = true; */
valueAxis.renderer.minGridDistance = 20;
// Create series
var series = chart.series.push(new am4charts.LineSeries());
series.dataFields.valueY = "price";
series.dataFields.dateX = "date";
series.strokeWidth = 3;
// series.propertyFields.stroke = "color";
series.smoothing = "monotoneX"; // <--- HERE
var bullet = series.bullets.push(new am4charts.CircleBullet());
bullet.circle.fill = am4core.color("#fff");
bullet.circle.strokeWidth = 3;
// Add cursor
chart.cursor = new am4charts.XYCursor();
chart.cursor.fullWidthLineX = true;
chart.cursor.xAxis = dateAxis;
chart.cursor.lineX.strokeWidth = 0;
chart.cursor.lineX.fill = am4core.color("#000");
chart.cursor.lineX.fillOpacity = 0.1;
// Add scrollbar
chart.scrollbarX = new am4core.Scrollbar();
// Add a guide
let range = valueAxis.axisRanges.create();
range.value = 90.4;
range.grid.stroke = am4core.color("#396478");
range.grid.strokeWidth = 1;
range.grid.strokeOpacity = 1;
range.grid.strokeDasharray = "3,3";
range.label.inside = true;
range.label.text = "Average";
range.label.fill = range.grid.stroke;
range.label.verticalCenter = "bottom";
// ========================= HERE =========================
function colorize(startDate, endDate, color) {
var range = dateAxis.createSeriesRange(series);
range.date = new Date(startDate + " 12:00");
range.endDate = new Date(endDate + " 12:00");
range.contents.stroke = am4core.color(color);
}
for (var i = 0; i < chart.data.length; i++) {
var startDate = chart.data[i].date,
endDate = (i < chart.data.length - 1) && chart.data[i + 1].date,
color = chart.data[i].color;
colorize(startDate, endDate, color);
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}
#chartdiv {
width: 100%;
height: 500px;
}
<script src="https://cdn.amcharts.com/lib/4/core.js"></script>
<script src="https://cdn.amcharts.com/lib/4/charts.js"></script>
<script src="https://cdn.amcharts.com/lib/4/themes/animated.js"></script>
<div id="chartdiv"></div>

amcharts valueaxis incremental manner scaling

I have value range from 1 to 40 000 which I am trying to plot on amcharts serial chart. As chart is auto scaling depend on value range, values which are less than 500 (ex: 10, 50, 100...) are shown as line on x-axis itself. In this case auto scaling is 0-1000-2000-3000...
How to achieve scaling in incremental manner i.e. 0-10-100-1000-10000 ... so that all candles including low value candles also get significant visibility.
or suggest any better approach to get all chart candles visible in chart.
<style>
#chartdiv {
width: 100%;
height: 500px;
}
</style>
<!-- Resources -->
<script src="https://www.amcharts.com/lib/4/core.js">
</script>
<script src="https://www.amcharts.com/lib/4/charts.js">
</script>
<script>
src=
"https://www.amcharts.com/lib/4/themes/animated.js" >
</script>
<!-- Chart code -->
<script>
am4core.ready(function() {
// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end
// Create chart instance
var chart = am4core.create("chartdiv",
am4charts.XYChart3D);
// Adding sample data
chart.data = [{
"country": "USA",
"visits": 39000
}, {
"country": "China",
"visits": 100
}, {
"country": "Japan",
"visits": 35000
}, {
"country": "Germany",
"visits": 50
}, {
"country": "UK",
"visits": 200
}, {
"country": "France",
"visits": 20
}, {
"country": "India",
"visits": 25
}, {
"country": "Spain",
"visits": 711
} ];
// Create axes
let categoryAxis = chart.xAxes.push(new
am4charts.CategoryAxis());
categoryAxis.dataFields.category = "country";
categoryAxis.renderer.labels.template.rotation = 270;
categoryAxis.renderer.labels.template.hideOversized =
false;
categoryAxis.renderer.minGridDistance = 20;
categoryAxis.renderer.labels.template.horizontalCenter =
"right";
categoryAxis.renderer.labels.template.verticalCenter =
"middle";
categoryAxis.tooltip.label.rotation = 270;
categoryAxis.tooltip.label.horizontalCenter = "right";
categoryAxis.tooltip.label.verticalCenter = "middle";
let valueAxis = chart.yAxes.push(new
am4charts.ValueAxis());
valueAxis.title.text = "Countries";
valueAxis.title.fontWeight = "bold";
// Create series
var series = chart.series.push(new
am4charts.ColumnSeries3D());
series.dataFields.valueY = "visits";
series.dataFields.categoryX = "country";
series.name = "Visits";
series.tooltipText = "{categoryX}: [bold]{valueY}[/]";
series.columns.template.fillOpacity = .8;
var columnTemplate = series.columns.template;
columnTemplate.strokeWidth = 2;
columnTemplate.strokeOpacity = 1;
columnTemplate.stroke = am4core.color("#FFFFFF");
columnTemplate.adapter.add("fill", (fill, target) => {
return chart.colors.getIndex(target.dataItem.index);
})
columnTemplate.adapter.add("stroke", (stroke, target) =>
{
return chart.colors.getIndex(target.dataItem.index);
})
chart.cursor = new am4charts.XYCursor();
chart.cursor.lineX.strokeOpacity = 0;
chart.cursor.lineY.strokeOpacity = 0;
}); // end am4core.ready()
</script>
<!-- HTML -->
<div id="chartdiv"></div>
You can achieve this by setting:
valueAxis.logarithmic = true;

Convert amCharts stock chart period selector into a dropdown

I am using amCharts stock chart to show trades within a period of time. I am using php and ajax to get values.
Now I do have period selector as buttons but I need them as a select. When a user selects a value from dropdown, the chart zoom should change accordingly. Is it possible to do that?
Below is my code to get a stock chart. Please help.
<div id="chartdiv" style="width:100%; height:400px;"></div>
<select id="mySelect" onchange="test()">
<option value="5">5
<option value="15">15
<option value="30">30
<option value="60">1H
<option value="D">1D
</select>
<script type="text/javascript">
AmCharts.addInitHandler(function (chart) {
}, ["stock"]);
var chartData = generateChartData();
console.log(chartData);
var chart = AmCharts.makeChart("chartdiv", {
"type": "stock",
"theme": "light",
"autoMarginOffset": 30,
"valueAxesSettings": {
"position": "right",
"inside": false,
"autoMargins": true,
"axisColor": "#000000",
"tickLength": 1
},
"categoryAxesSettings": {
"parseDates": true,
"minPeriod": "ss",
"axisColor": "#000000",
"tickLength": 1
},
"mouseWheelZoomEnabled": true,
"dataSets": [{
"fieldMappings": [{
"fromField": "open",
"toField": "open"
}, {
"fromField": "close",
"toField": "close"
}, {
"fromField": "high",
"toField": "high"
}, {
"fromField": "low",
"toField": "low"
}, {
"fromField": "volume",
"toField": "volume"
}],
"color": "#7f8da9",
"dataProvider": chartData,
"title": '<?php echo $symbol; ?>',
"categoryField": "date"
}
],
"panels": [{
"urlTarget": "_blank",
"showCategoryAxis": true,
"percentHeight": 70,
"valueAxes": [{
"dashLength": 5
}],
"categoryAxis": {
"dashLength": 5
},
"stockGraphs": [{
"id": "g1",
"type": "candlestick",
"proCandlesticks": false,
"balloonText": "Open:<b>[[open]]</b><br>Low:<b>[[low]]</b><br>High:<b>[[high]]</b><br>Close:<b>[[close]]</b><br>",
"openField": "open",
"closeField": "close",
"highField": "high",
"lowField": "low",
"lineAlpha": 1,
"lineColor": "#53b987",
"fillColors": "#53b987",
"fillAlphas": 0.9,
"negativeFillColors": "#eb4d5c",
"negativeLineColor": "#eb4d5c",
"useDataSetColors": false,
"title": "Volume:",
"valueField": "volume"
}],
"stockLegend": {
"valueTextRegular": undefined,
"periodValueTextComparing": "[[percents.value.close]]%"
}
}
],
"chartScrollbarSettings": {
"updateOnReleaseOnly": true,
"autoGridCount": true,
"graph": "g1",
"graphType": "line",
"scrollbarHeight": 30
},
"periodSelector": {
"position": "top",
"inputFieldsEnabled": false,
"periodsText": "",
"dateFormat": "YYYY-MM-DD JJ:NN",
"periods": [{
"period": "hh",
"count": 1,
"label": "5",
"selected": true
}, {
"period": "hh",
"count": 6,
"label": "15"
}, {
"period": "hh",
"count": 4,
"label": "30"
}, {
"period": "hh",
"count": 12,
"label": "1H"
}, {
"period": "dd",
"count": 60,
"label": "1D"
}]
},
"listeners": [
{
"event": "rendered",
"method": function (e) {
if (e.chart.ignoreResize) {
e.chart.ignoreResize = false;
return;
}
// init
var margins = {
"left": 0,
"right": 0
};
// iterate thorugh all of the panels
for (var p = 0; p < chart.panels.length; p++) {
var panel = chart.panels[p];
// iterate through all of the axis
for (var i = 0; i < panel.valueAxes.length; i++) {
var axis = panel.valueAxes[i];
if (axis.inside !== false) {
continue;
}
var axisWidth = axis.getBBox().width + 10;
if (axisWidth > margins[axis.position]) {
margins[axis.position] = axisWidth;
}
}
}
// set margins
if (margins.left || margins.right) {
chart.panelsSettings.marginLeft = margins.left;
chart.panelsSettings.marginRight = margins.right;
e.chart.ignoreResize = true;
chart.invalidateSize();
}
}
},
{
"event": "zoomed",
"method": function (e) {
e.chart.lastZoomed = e;
//console.log(e);
console.log("ignoring zoomed");
}
},
]
});
setInterval(function () {
//Setting the new data to the graph
chart.dataProvider = generateChartData();
chart.validateData();
}, 10000);
function test() {
var resolution = $("#mySelect").val();
//console.log(resolution);
var pp, count;
if (resolution == "D") {
resolution = "1D";
pp = 'dd';
count = 60;
}
else if (resolution == "60") {
resolution = "1H";
pp = 'hh';
count = 12;
}
else if (resolution == "30") {
pp = 'hh';
count = 4;
}
else if (resolution == "15") {
pp = 'hh';
count = 6;
}
else if (resolution == "5") {
pp = 'hh';
count = 1;
}
else {
pp = 'hh';
}
//console.log(pp);
for (var x in chart.periodSelector.periods) {
var period = chart.periodSelector.periods[x];
if (pp == period.period && resolution == period.count) {
period.selected = true;
}
else {
period.selected = false;
}
}
// console.log(period.period);
chart.periodSelector.setDefaultPeriod();
}
</script>

loading json data How to show clustered bar charts in dynamic graphs

Updated
Can you possible graphs value dynamic.
Below code pass a static value but i get dynamic code graphs.
Example: resultx get 3-4 subcategory i every time define graphs value.
var processedChartData = resultx.map(function(rawDataElement) {
var newDataElement = { "category": rawDataElement.category };
rawDataElement.data.forEach(function(nestedElement, index) {
newDataElement["value" + index] = nestedElement.value;
newDataElement["subcategory" + index] = nestedElement.subcategory
});
return newDataElement;
});
AmCharts.makeChart(id, {
"type": "serial",
"theme": "light",
"categoryField": "category",
"rotate": false,
"startDuration": 0,
"categoryAxis": {
"gridPosition": "start",
"position": "left"
},
"graphs": [{
"fillAlphas": 0.9,
"lineAlpha": 0.2,
"title": "2004",
"type": "column",
"balloonText": "[[subcategory0]]: [[value]]",
"valueField": "value0"
}, {
"fillAlphas": 0.9,
"lineAlpha": 0.2,
"title": "2005",
"type": "column",
"balloonText": "[[subcategory1]]: [[value]]",
"valueField": "value1"
},
{
"fillAlphas": 0.9,
"lineAlpha": 0.2,
"title": "2005",
"type": "column",
"balloonText": "[[subcategory2]]: [[value]]",
"valueField": "value2",
}],
"guides": [],
"allLabels": [],
"balloon": {},
"titles": [],
"dataProvider": processedChartData,
"export": {
"enabled":false
}
});
Original question:
Clustered bar charts Array inside key how to display multiple bar charts.
My json below:
[
{
"0":
{
"package_sold":"88",
"vSectorName":"Meat"
},
"country":"France"
},
{
"0":
{
"package_sold":"68",
"vSectorName":"Meat"
},
"1":
{
"package_sold":"151",
"vSectorName":"Poultry"
},
"country":"United Kingdom"
}
]
How to show in graph dataProvider
AmCharts doesn't support nested JSON. You'll need to flatten your JSON into a single object so that your valueFields are distinct in each element of your array.
For example, this:
{
"0":
{
"package_sold":"68",
"vSectorName":"Meat"
},
"1":
{
"package_sold":"151",
"vSectorName":"Poultry"
},
"country":"United Kingdom"
}
can be turned into this:
{
"Meat_package_sold": 68,
"Poultry_package_sold": 151,
"country": "United Kingdom"
}
From there you can set your graph valueField to "Meat_package_sold" and "Poultry_package_sold". I'm assuming your categoryField is "country".
You'll either need to change your backend or write some some JS to remap your data to a format that AmCharts can recognize.
Edit: Here's a basic example that remaps your JSON data using JS:
var rawData = [{
"0": {
"package_sold": "88",
"vSectorName": "Meat"
},
"country": "France"
},
{
"0": {
"package_sold": "68",
"vSectorName": "Meat"
},
"1": {
"package_sold": "151",
"vSectorName": "Poultry"
},
"country": "United Kingdom"
}
]
var newData = [];
rawData.forEach(function(dataItem) {
var newDataItem = {};
Object.keys(dataItem).forEach(function(key) {
if (typeof dataItem[key] === "object") {
newDataItem[dataItem[key]["vSectorName"] + "_package_sold"] = dataItem[key]["package_sold"];
} else {
newDataItem[key] = dataItem[key];
}
});
newData.push(newDataItem);
});
console.log(JSON.stringify(newData));
Demo of your chart using the correct JSON format:
var chart = AmCharts.makeChart("chartdiv", {
"type": "serial",
"theme": "light",
"categoryField": "country",
"graphs": [{
"fillAlphas": 0.8,
"lineAlpha": 0.2,
"type": "column",
"valueField": "Meat_package_sold"
},
{
"fillAlphas": 0.8,
"lineAlpha": 0.2,
"type": "column",
"valueField": "Poultry_package_sold"
}
],
"dataProvider": [{
"Meat_package_sold": 88,
"country": "France",
}, {
"Meat_package_sold": 68,
"Poultry_package_sold": 151,
"country": "United Kingdom"
}, {
"Meat_package_sold": 120,
"Poultry_package_sold": 110,
"country": "Germany"
}]
});
html,
body {
width: 100%;
height: 100%;
margin: 0px;
}
#chartdiv {
width: 100%;
height: 100%;
}
<script src="//www.amcharts.com/lib/3/amcharts.js"></script>
<script src="//www.amcharts.com/lib/3/serial.js"></script>
<script src="//www.amcharts.com/lib/3/themes/light.js"></script>
<div id="chartdiv"></div>
This is dynamic json data, but to show how to use and build I defined it so.
In actual, i use ajax to get json data and then building it dynamically.
Here I had Generate Graph,GLName against its opening for each month comparatively. hope it will helpful for all
var resp=[
{
"MONTH_": "01",
"MONTH_NAME": "JAN",
"YEAR_": "2018",
"GL_NAME": "CASH,FACTORY, SITE,OFFICE ",
"GL_ID": "79,81,522,89",
"OPENING": "606294,0,24851,170392",
"RECEIPT": "1641300,40000,210850,82300",
"PAYMENT": "2074921,103209,168893,40000",
"CLOSING": "172673,149483,66808,0"
},
{
"MONTH_": "02",
"MONTH_NAME": "FEB",
"YEAR_": "2018",
"GL_NAME": " SITE,CASH,OFFICE ,FACTORY",
"GL_ID": "81,79,522,89",
"OPENING": "66808,172673,0,149483",
"RECEIPT": "102650,40000,3479000,200000",
"PAYMENT": "239379,168339,40000,3388527",
"CLOSING": "-69921,0,181144,263146"
},
{
"MONTH_": "03",
"MONTH_NAME": "MAR",
"YEAR_": "2018",
"GL_NAME": "FACTORY,CASH,OFFICE , SITE",
"GL_ID": "89,81,79,522",
"OPENING": "181144,-69921,0,263146",
"RECEIPT": "30000,40000,1943500,200000",
"PAYMENT": "69242,1806551,18177",
"CLOSING": "141902,400095,40000,111902"
}
]
var newChartDataArr = [];
var colNameArr = [];
var GLID = [];
var amtArr = [];
var newBarGraph = [];
myJsonString1 = JSON.stringify(resp);
var obj = JSON.parse(myJsonString1);
var obj1 = resp[0];
//spliting of GLName
if (obj1.GL_NAME.toString().indexOf(',') != -1) {
colNameArr = obj1.GL_NAME.split(',');
GLID =obj1.GL_ID.split(',');
} else {
colNameArr.push(obj1.GL_NAME);
GLID =obj1.GL_ID.split(',');
}
//Getting Month and Opening of GL
$.each(resp, function (i, value) {
var newObj = {};
newObj['MONTH_NAME'] = value.MONTH_NAME+"-"+value.YEAR_;
$.each(value, function (k, v) {
if (k == 'OPENING') {
for (var i = 0; i < colNameArr.length; i++) {
if (v.toString().indexOf(',') != -1) {
newObj[colNameArr[i]] = parseFloat(v.split(',')[i]);
} else {
newObj[colNameArr[i]] = parseFloat(v);
}
}
}
});
newChartDataArr.push(newObj); //GL with Opening
});
for (var i = 0; i < colNameArr.length; i++) {
let graph = {};
graph["id"] = "v-"+GLID[i];
graph["balloonText"] = colNameArr[i] + " [[category]] Amount:[[value]]",
graph["title"] = colNameArr[i];
graph["valueField"] = colNameArr[i];
graph["fillAlphas"] = 0.8;
graph["lineAlpha"] = 0.2;
graph["type"] = "column";
newBarGraph.push(graph);
}
chart = AmCharts.makeChart("Monthdiv", {
"type": "serial",
"theme": "light",
"categoryField": "MONTH_NAME",
"startDuration": 1,
"trendLines": [],
"legend": {
"position": "bottom",
"maxColumns": 2,
"useGraphSettings": true
},
"depth3D": 10,
"angle": 60,
"graphs": newBarGraph,
"guides": [],
"valueAxes": [
{
"position": "left",
"title": "Opening"
}
],
"categoryAxis": {
"gridPosition": "start",
"labelRotation": 90,
"title": "Months"
},
"allLabels": [],
"balloon": {},
"titles": [{
"text":"Monthly Sale"
}],
"dataProvider": newChartDataArr,
"export": {
"enabled": true
},
"listeners": [{
"event": "clickGraphItem",
"method": function (event) {
var gl_ID=(event.item.graph.id).slice(2);
var month = (event.item.category).slice(0, 3);
var calender = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'];
var monthVal = calender.indexOf(month) + 1;
var year = (event.item.category).slice(4, 8);
$("#fromDate").val("01/" + monthVal + "/" + year);
$("#toDate").val("30/" + monthVal + "/" + year);
Daliy(gl_ID,event.item.category);
showSummary();
}
}]
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Resources -->
<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/themes/light.js"></script>
<div class="col-sm-12" id="Monthdiv" style="height: 370px;">

Google API v3 MarkerCluster and AJAX failing to display grouped markers

I have looked at the linked answer but although I thought I logically follow it's flow I can't apply it to my code:
Google Maps API Marker Clusterer and Ajax
I can't figure out where to place markerCluster.add(markers); When I had the JSON documents loaded from a file I had no trouble.
Any help would be appreciated.
/****
Google Map
****/
function renderMap() {
var myLatlng = new google.maps.LatLng(53.270433, -9.054760999999985);
var myOptions = {
zoom: 6,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById("map-canvas"), myOptions);
var iconBase = 'http://temp.net/sites/recall/images/';
var markerCluster = new MarkerClusterer(map, {averageCenter: true, gridSize: 40});
var markers = [];
/****
Create Markers and bind events. recall loaded from HTML
****/
$.ajax({
type: "GET",
dataType: "json",
url: "*************",
success: function (data) {
$.each(data[0], function () {
if (this.$oid == null) {
var markerPos = new google.maps.LatLng(this.lat, this.lng);
var marker = new google.maps.Marker({
position: markerPos,
map: map,
title: this.title,
icon: iconBase + this.icon
});
markers.push(marker);
var pano = null;
var data = this;
/****
Closure
****/
(function (marker, data) {
google.maps.event.addListener(marker, 'click', function (e) {
map.setZoom(19);
map.setCenter(marker.getPosition());
map.setMapTypeId(google.maps.MapTypeId.HYBRID);
$("#slider-horizontal").on().delay(500).fadeIn('2000');
if (pano != null) {
pano.unbind("position");
pano.setVisible(false);
}
var panoramaOptions = {
navigationControl: false,
navigationControlOptions: {style: google.maps.NavigationControlStyle.ANDROID},
enableCloseButton: true,
addressControl: false,
linksControl: false,
panControl: false,
clickToGo: false,
scrollwheel: false,
draggable: false,
panControl: false,
enableCloseButton: true,
pov: {
heading: eval(data.heading),
pitch: eval(data.pitch),
zoom: eval(data.zoom)
}
}
pano = new google.maps.StreetViewPanorama(document.getElementById("map-canvas"), panoramaOptions);
pano.bindTo("position", marker);
pano.setVisible(true);
var closeButton = document.querySelector('.images');
google.maps.event.addDomListener(closeButton, 'click', function () {
pano.setVisible(false);
});
google.maps.event.addListener(pano, 'visible_changed', function () {
$('#slider-horizontal').on().slider('value', 1).hide();
$('.images .old').css('opacity', 1);
map.setZoom(20);
});
});
})(marker, data);
/****
END Closure
****/
}
});
}
});
/****
END $.each(recall, function()
****/
google.maps.event.addListener(map, 'zoom_changed', function () {
zoom = map.getZoom();
if (zoom < 15) {
map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
} else {
map.setMapTypeId(google.maps.MapTypeId.HYBRID);
}
});
//{gridSize: 40} to prevent markers from being grouped even at max zoom
//var markerCluster = new MarkerClusterer(map, markers, {averageCenter: true, gridSize: 40});
}//END renderMap()
renderMap();
SAMPLE DATA:
Currently REST returns:
[
{
"_id": {
"$oid": "51c4e7375c90fdb357954af1"
},
"jfkmotorcade": {
"class": "jfkmotorcade",
"image": "jfk_motorcade.jpg",
"lat": "53.26648",
"lng": "-9.070578999999952",
"title": "JFK Motorcade",
"icon": "president_seal_small.png",
"heading": "56.40777127701934",
"pitch": "-1.3747348931946495",
"zoom": "1.5",
"date": "",
"comments": {},
"tags": {}
}
}
]
but I will be changing it to:
{
"class": "jfkmotorcade",
"image": "jfk_motorcade.jpg",
"lat": "53.26648",
"lng": "-9.070578999999952",
"title": "JFK Motorcade",
"icon": "president_seal_small.png",
"heading": "56.40777127701934",
"pitch": "-1.3747348931946495",
"zoom": "1.5",
"date": "",
"comments": {},
"tags": {}
}
You have a scope problem with your map variable. If I make it global it works.
var map = null;
function renderMap() {
var myLatlng = new google.maps.LatLng(53.270433, -9.054760999999985);
var myOptions = {
zoom: 6,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map-canvas"), myOptions);
// ...
(although as you only provided one piece of data, it doesn't cluster...)
I managed to get around by problem by creating a variable to get the AJAX call into the correct Scope.
Here's some extra data:
[
{
"_id": {
"$oid": "51c4e7375c90fdb357954af1"
},
"jfkmotorcade": {
"class": "jfkmotorcade",
"image": "jfk_motorcade.jpg",
"lat": "53.26648",
"lng": "-9.070578999999952",
"title": "JFK Motorcade",
"icon": "president_seal_small.png",
"heading": "56.40777127701934",
"pitch": "-1.3747348931946495",
"zoom": "1.5",
"date": "",
"comments": {},
"tags": {}
},
"quaystreet": {
"class": "quaystreet",
"image": "quay-street-old.jpg",
"lat": "53.270433",
"lng": "-9.054760999999985",
"title": "Quay Street",
"icon": "camera_small.png",
"heading": "27.33813250741931",
"pitch": "-0.593156926724266",
"zoom": "1.5",
"date": "",
"comments": {},
"tags": {}
},
"spannish_arch": {
"class": "spannish_arch",
"image": "spannish_arch.jpg",
"lat": "53.270365",
"lng": "-9.054955000000064",
"title": "Spanish Arch",
"icon": "camera_small.png",
"heading": "143.84352819857685",
"pitch": "-2.9656547695268896",
"zoom": "1.17",
"date": "",
"comments": {},
"tags": {}
}
}
]
FIXED CODE
/****
Collect Data from RESTful Service
****/
recall = {};
$.ajax({
type: "GET",
dataType: "json",
url: "*********************",
success: function (data) {
$.each(data[0], function () {
if (this.$oid == null)
alert(this.class);
});
recall = data[0];
renderMap();
}
});
/****
Google Map
****/
function renderMap() {
var myLatlng = new google.maps.LatLng(53.270433, -9.054760999999985);
var myOptions = {
zoom: 6,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById("map-canvas"), myOptions);
var iconBase = 'http://temp.net/sites/recall/images/';
var markers = [];
/****
Create Markers and bind events. recall loaded from HTML
****/
$.each(recall, function () {
/*place holder $.each(this, function(k, v) {
});*/
if (this.$oid == null)
{
var markerPos = new google.maps.LatLng(this.lat, this.lng);
var marker = new google.maps.Marker({
position: markerPos,
map: map,
title: this.title,
icon: iconBase + this.icon
});
markers.push(marker);
var pano = null;
var data = this;
/****
Closure
****/
(function (marker, data) {
google.maps.event.addListener(marker, 'click', function (e) {
map.setZoom(19);
map.setCenter(marker.getPosition());
map.setMapTypeId(google.maps.MapTypeId.HYBRID);
$("#slider-horizontal").on().delay(500).fadeIn('2000');
if (pano != null) {
pano.unbind("position");
pano.setVisible(false);
}
var panoramaOptions = {
navigationControl: false,
navigationControlOptions: {style: google.maps.NavigationControlStyle.ANDROID},
enableCloseButton: true,
addressControl: false,
linksControl: false,
panControl: false,
clickToGo: false,
scrollwheel: false,
draggable: false,
panControl: false,
enableCloseButton: true,
pov: {
heading: eval(data.heading),
pitch: eval(data.pitch),
zoom: eval(data.zoom)
}
}
pano = new google.maps.StreetViewPanorama(document.getElementById("map-canvas"), panoramaOptions);
pano.bindTo("position", marker);
pano.setVisible(true);
var closeButton = document.querySelector('.images');
google.maps.event.addDomListener(closeButton, 'click', function () {
pano.setVisible(false);
});
google.maps.event.addListener(pano, 'visible_changed', function () {
$('#slider-horizontal').on().slider('value', 1).hide();
$('.images .old').css('opacity', 1);
map.setZoom(20);
});
});
})(marker, data);
/****
END Closure
****/
}
});
/****
END $.each(recall, function()
****/
google.maps.event.addListener(map, 'zoom_changed', function () {
zoom = map.getZoom();
if (zoom < 15) {
map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
} else {
map.setMapTypeId(google.maps.MapTypeId.HYBRID);
}
});
//{gridSize: 40} to prevent markers from being grouped even at max zoom
var markerCluster = new MarkerClusterer(map, markers, {averageCenter: true, gridSize: 40});
}//END renderMap()
/****
END Google Map
****/

Resources