My HTML code is like this :
<div id="chartdiv" style="width: 100%; height: 362px;"></div>
My Javascript code is like this :
var chart;
var legend;
var chartData = [
{
"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
}
];
console.log(chartData);
AmCharts.ready(function () {
// PIE CHART
chart = new AmCharts.AmPieChart();
chart.dataProvider = chartData;
chart.titleField = "country";
chart.valueField = "litres";
// WRITE
chart.write("chartdiv");
});
Demo and complete code is like this : https://jsfiddle.net/oscar11/4qdan7k7/2/
I want to change amchart themes like this : https://www.amcharts.com/demos/simple-pie-chart/
I add light.js library, but the themes not change
Any solution to solve my problem?
You need to specify the theme option while initializing as below and also make use of makeChart directly instead of Amcharts.AmPieChart(). Your updated code would be:
AmCharts.makeChart("chartdiv", {
"type": "pie",
"theme": "light",
"dataProvider": chartData,
"valueField": "litres",
"titleField": "country",
"export": {
"enabled": true
}
});
UPDATED FIDDLE
Related
I would like to know how to add a listener that only runs once, I believe in the end this is mostly a generic javascript question, but I might be missing something.
Here's what I have :
const listener = chart.addListener('rendered', () => {
console.log('Chart rendered! This should only print once!');
doSomethingToChart(chart);
chart.removeListener(chart, 'rendered', listener);
})
The problem here is, is not removing the listener, the console.log is printing on each render. How can I fix this?
addListener doesn't have a return value at all, nor makes any mention of one in the documentation, which is why your code doesn't work. Just store the function reference separately before you add the listner, then call removeListener on that reference and it will work, for example:
let counter = 0;
const listener = () => {
console.log('dataUpdated called', counter += 1);
};
chart.addListener('dataUpdated', listener);
let timer = setInterval(() => {
chart.validateData(); //triggers dataUpdated
if (counter == 3) {
chart.removeListener(chart, 'dataUpdated', listener);
console.log('dataUpdated removed')
chart.validateData(); //one more call to confirm that the listner no longer runs
clearInterval(timer);
}
}, 1500);
Demo:
var chart = AmCharts.makeChart("chartdiv", {
"type": "serial",
"theme": "light",
"dataProvider": [{
"country": "USA",
"visits": 2025
}, {
"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
}],
"graphs": [{
"fillAlphas": 0.9,
"lineAlpha": 0.2,
"type": "column",
"valueField": "visits"
}],
"categoryField": "country"
}, 100);
let counter = 0;
const listener = () => {
console.log('dataUpdated called', counter += 1);
};
chart.addListener('dataUpdated', listener);
let timer = setInterval(() => {
chart.validateData(); //this triggers dataUpdated
if (counter == 3) {
chart.removeListener(chart, 'dataUpdated', listener);
console.log('dataUpdated removed')
chart.validateData(); //confirm that listner isn't called anymore
clearInterval(timer);
}
}, 1500);
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>
Just use use the listener like this:
const listener = () => {
console.log('Chart rendered! This should only print once!');
// ...
chart.removeListener(chart, 'rendered', listener);
};
chart.addListener('rendered', listener);
Here is a codepen showing the behavior.
Alternatively you can use an external variable to save the state:
let executedOnce = false;
chart.addListener('rendered', () => {
if (executedOnce) {
return;
}
executedOnce = true;
console.log('Chart rendered! This should only print once!');
// ...
});
Beside that I would recommend switching to amcharts4, because it is much more flexible and has even new chart types. You can migrate easily, beginning with just one chart. You can use amcharts3 and amcharts4 in parallel (Migration Guide).
In amcharts4 you can subscribe once to an event (docs):
chart.events.once('datavalidated' => {
// ...
});
I am starting using amcharts 4 and I have run into issue: according to the docs to change charts dataset all it takes is to assign new array of objects to the chart.data:
chart.data = [{ some data object }, {}......]
It does it seems to be working for me, please see this codepen: https://codepen.io/anon/pen/LMgEjV
/**
* ---------------------------------------
* 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/
* ---------------------------------------
*/
// Create chart instance
var chart = am4core.create("chartdiv", am4charts.PieChart);
// Add data
chart.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 = chart.series.push(new am4charts.PieSeries());
pieSeries.dataFields.value = "litres";
pieSeries.dataFields.category = "country";
function changeData() {
chart.data = [{
"country": "Lithuania",
"litres": 501.9
}, {
"country": "Czech Republic",
"litres": 301.9
}
];
chart.validateData();
}
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: 400px;
}
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<button id="btn-change" onClick="changeData()">Click Me</button>
<div id="chartdiv"></div>
What am I missing?
I am not 100% sure I understood the problem but I will try to help you anyway, I checked your code and I think the main problem happened because you push entire array to the chart.data instead of just the object you want to change. please see my code:
function changeData() {
chart.data.push({
"country": "Lithuania",
"litres": "501.9"
})
chart.validateData();
}
I want to pass php results to javascript charts.
<script>
<?php foreach ($hourlyreport as $val) {?>
var chart = AmCharts.makeChart( "chartdiv", {
"type": "pie",
"theme": "light",
"dataProvider": [ {
"country": "totalstaff",
"litres": <?php echo $val->totalstaff;?>
}, {
"country": "totaltasks",
"litres": <?php echo $val->totaltasks;?>
}, {
"country": "completed tasks",
"litres": <?php echo $val->is_completed;?>
}, {
"country": "pendingtasks",
"litres": <?php echo $pending;?>
}
],
"valueField": "litres",
"titleField": "country",
"balloon":{
"fixedPosition":true
},
"export": {
"enabled": true
}
} );
<?php } ?>
</script>
This is my chart script, I'm passing foreach results to this charts. On client side HTML page has code something like below.
<div id="chartdiv">
</div>
<?php
$value='';
foreach ($hourlyreport as $val) {
$value='{
"type": "pie",
"theme": "light",
"dataProvider": [ {
"country": "totalstaff",
"litres": <?php echo $val->totalstaff;?>
}, {
"country": "totaltasks",
"litres": <?php echo $val->totaltasks;?>
}, {
"country": "completed tasks",
"litres": <?php echo $val->is_completed;?>
}, {
"country": "pendingtasks",
"litres": <?php echo $pending;?>
}
],
"valueField": "litres",
"titleField": "country",
"balloon":{
"fixedPosition":true
},
"export": {
"enabled": true
}
} ' ;
} ?>
<script>
var chart = AmCharts.makeChart( "chartdiv",<?php echo $value;?>);
</script>
OutPut
<script> var chart = AmCharts.makeChart( "chartdiv",{ "type": "pie", "theme": "light", "dataProvider": [ { "country": "totalstaff", "litres": $val->totalstaff; }, { "country": "totaltasks", "litres": $val->totaltasks; }, { "country": "completed tasks", "litres": $val->is_completed; }, { "country": "pendingtasks", "litres": $pending; } ], "valueField": "litres", "titleField": "country", "balloon":{ "fixedPosition":true }, "export": { "enabled": true } } ); </script>
You are running the loop for the whole chart object so it is try to create multiple chart object.That's why it is not working. I have done this in my project.
Try this it will work for you
<script>
var chart = AmCharts.makeChart( "chartdiv", {
"type": "pie",
"theme": "light",
"dataProvider": [
<?php foreach ($hourlyreport as $val) {?>
{
"country": "totalstaff",
"litres": '<?php echo $val->totalstaff;?>'
}, {
"country": "totaltasks",
"litres": '<?php echo $val->totaltasks;?>'
}, {
"country": "completed tasks",
"litres": '<?php echo $val->is_completed;?>'
}, {
"country": "pendingtasks",
"litres": '<?php echo $pending;?>'
}
<?php } ?>
],
"valueField": "litres",
"titleField": "country",
"balloon":{
"fixedPosition":true
},
"export": {
"enabled": true
}
} );
</script>
I have a bar chart from amcharts. I need to highlight a single bar on click on bar. Current scenario is when I click multiple bar, all bars highlighted.
Here is my code
"listeners": [{
"event": "clickGraphItem",
"method": function(event) {
var node = event.item.columnGraphics.node.lastChild;
node.setAttribute("stroke","#8198b4");
node.setAttribute("fill","#8198b4");
}
}]
Any help? Thank You.
Instead of modifying the node, use fillColorsField instead, which allows you to set/unset the currently selected column's highlight and allows you to go through the rest of the chart's data to make sure only one item is selected.
"graphs": [{
// ...
"fillColorsField": "selected"
}],
"zoomOutOnDataUpdate": false, //recommended so that the chart doesn't reset the current zoom after clicking on a column
"listeners": [{
"event": "clickGraphItem",
"method": function(e) {
//if the current item is already selected, deselect it
if (e.item.dataContext.selected) {
e.item.dataContext.selected = undefined;
}
else {
//otherwise, find any other columns that were selected and deselect them
for (var i = 0; i < e.chart.dataProvider.length; ++i) {
if (e.chart.dataProvider[i].selected) {
e.chart.dataProvider[i].selected = undefined;
break;
}
}
e.item.dataContext.selected = "#8198b4";
}
e.chart.validateData(); //update chart
}
}]
Demo below:
var chart = AmCharts.makeChart("chartdiv", {
"type": "serial",
"dataProvider": [{
"country": "USA",
"visits": 2025
}, {
"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
}],
"graphs": [{
"fillAlphas": 0.9,
"lineAlpha": 0.2,
"type": "column",
"valueField": "visits",
"fillColorsField": "selected"
}],
"categoryField": "country",
"zoomOutOnDataUpdate": false, //recommended so that the chart doesn't reset the current zoom after clicking on a column
"listeners": [{
"event": "clickGraphItem",
"method": function(e) {
//if the current item is already selected, deselect it
if (e.item.dataContext.selected) {
e.item.dataContext.selected = undefined;
}
else {
//otherwise, find any other columns that were selected and deselect them
for (var i = 0; i < e.chart.dataProvider.length; ++i) {
if (e.chart.dataProvider[i].selected) {
e.chart.dataProvider[i].selected = undefined;
break;
}
}
e.item.dataContext.selected = "#8198b4";
}
e.chart.validateData(); //update chart
}
}]
});
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>
<div id="chartdiv"></div>
I have some issues with serial chart (Column With Rotated Series).
My dataProvider does not have a color field. I used the colors option with an array of colors, but it still does not work.
Please help me.
http://jsfiddle.net/bfbgz0sc/1/
zeroin thank for your response ,
amCharts Help & Support said to me , each color within the array is reserved for every individual graph.
Unfortunately rather than defining all colors within the dataprovider is no other ways to do it.
Code Snippet:
//input data
var input=[{
"country": "USA",
"visits": 3025
}, {
"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
}];
//your custom colors
var colors= ['#FF6600', '#FCD202', '#B0DE09', '#0D8ECF', '#2A0CD0', '#CD0D74', '#CC0000', '#00CC00', '#0000CC', '#DDDDDD', '#999999', '#333333', '#990000']
//inject color attribute with value
for (i = 0; i < input.length; i++) {input[i].color = colors[i];}
//amCharts initialization code goes here
...
...
Output
Checkout this JSFiddle to see the solution in action:
http://jsfiddle.net/bfbgz0sc/4/
Colors property works only for separate graphs, not for data items. So you should add colors to dataProvider.