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
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>
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;
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>
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;">
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
****/