I use a nested pie chart to display hierarchic data, I would like to be able to display a specific color by box
For example here:
let's say I want to change the color only for this box from yellow to grey.
You can test it here : https://jsfiddle.net/aliz/gwz7om9e/
The javascript code:
(function(){
/*
Define all colors used.
*/
var colorSet = new am4core.ColorSet();
colorSet.list = ["#18dc08", "#e2ed0c", "#3be791", "#0eade6", "#8f55e9", "#dd0a4b"].map(function(color) {
return new am4core.color(color);
});
var size = 16.6;
/*
Creates a pie slice
*/
function createPie(chart, targetAttribute, positionRadiusInPie){
var pieSeries = chart.series.push(new am4charts.PieSeries());
pieSeries.dataFields.value = "size"; // the percentage size so all slice are equals
pieSeries.dataFields.category = "name";
pieSeries.slices.template.strokeWidth = 1;
pieSeries.slices.template.strokeOpacity = 1;
pieSeries.alignLabels = false;
pieSeries.ticks.template.disabled = true;
// Enable label
pieSeries.labels.template.text = "{"+ targetAttribute +".length}";
pieSeries.labels.template.radius = am4core.percent(positionRadiusInPie); // magic number
// color
pieSeries.colors = colorSet;
pieSeries.labels.template.fill = am4core.color("white");
pieSeries.slices.template.stroke = am4core.color("#fff");
// Disable sliding out of slices
//pieSeries.slices.template.states.getKey("hover").properties.shiftRadius = 0;
//pieSeries.slices.template.states.getKey("hover").properties.scale = 1.1;
// Tooltip conf
// https://www.amcharts.com/docs/v4/reference/pieseries/#Events
pieSeries.slices.template.events.on("over", function(ev){
// https://www.amcharts.com/docs/v4/tutorials/tooltips-with-rich-html-content/
var modalContent = [
'<center><strong>'+ev.target.dataItem.dataContext.name+'</strong></center>',
'<center><i>'+targetAttribute+'</i></center>',
'<hr />',
].join("");
if(!ev.target.dataItem.dataContext[targetAttribute] ||
ev.target.dataItem.dataContext[targetAttribute].length == 0){
modalContent += [
'<span>No information</span>'
].join("");
}else{
modalContent += [
'<table>',
'<tbody>'
].join("");
for(var i = 0; i < ev.target.dataItem.dataContext[targetAttribute].length; i++){
var item = ev.target.dataItem.dataContext[targetAttribute][i];
modalContent += [
'<tr>',
'<th align="left">Name</th>',
'<td align="right">'+item.name+'</td>',
'</tr>',
].join("");
}
modalContent += [
'</tbody>',
'</table>',
'<hr />'
].join("");
}
pieSeries.slices.template.tooltipHTML = modalContent;
}, this);
// https://www.amcharts.com/docs/v4/reference/columnseries/#Events
pieSeries.slices.template.events.on("inited", function(ev) {
if(!ev.target.dataItem.dataContext[targetAttribute] || ev.target.dataItem.dataContext[targetAttribute].length == 0){
ev.target.fillOpacity = 0.5;
}
}, this);
}
// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end
// Create chart instance
var chart = am4core.create("chartdiv", am4charts.PieChart);
// Let's cut a hole in our Pie chart the size of 20% the radius
chart.innerRadius = am4core.percent(20);
chart.pullOutRadius = 0;
// Add data: can be fetched from a webservice
chart.data = [
{
"name": "Sector1",
"color": colorSet.list[0].hex,
"size": size,
"category1": [
{
name: "test 1"
},
{
name: "titi"
}
],
"category2": [
//{
// name: "test 1"
// }
],
"category3" : [
//{
// name: "test 1"
//}
],
"category4" : [
{
name: "test 1"
}
]
},
{
"name": "Sector2",
"color": colorSet.list[1].hex,
"size": size,
"category1": [
{
name: "test 1"
}
],
"category2": [
{
name: "test 1"
}
],
"category3" : [
{
name: "test 1"
}
],
"category4" : [
{
name: "test 1"
}
]
},
{
"name": "Sector3",
"color": colorSet.list[2].hex,
"size": size,
"category1": [
{
name: "test 1"
}
],
"category2": [
//{
// name: "test 1"
//}
],
"category3" : [
{
name: "test 1"
}
],
"category4" : [
{
name: "test 1"
}
]
},
{
"name": "Sector4",
"color": colorSet.list[3].hex,
"size": size,
"category1": [
{
name: "test 1"
}
],
"category2": [
{
name: "test 1"
}
],
"category3" : [
{
name: "test 1"
}
],
"category4" : [
{
name: "test 1"
}
]
},
{
"name": "Sector5",
"color": colorSet.list[4].hex,
"size": size,
"category1": [
{
name: "test 1"
}
],
"category2": [
{
name: "test 1"
}
],
"category3" : [
{
name: "test 1"
}
],
"category4" : [
{
name: "test 1"
}
]
},
{
"name": "Sector6",
"color": colorSet.list[5].hex,
"size": size,
"category2": [
{
name: "test 1"
}
],
"category1": [
{
name: "test 1"
}
],
"category3" : [
{
name: "test 1"
}
],
"category4" : [
{
name: "test 1"
}
]
}
];
/*
category1
*/
createPie(chart, "category1", -28);
/*
category2
*/
createPie(chart, "category2", -20);
/*
category3
*/
createPie(chart, "category3", -10);
/*
Business ops
*/
createPie(chart, "category4", -8);
/*
Legend builder
// https://www.amcharts.com/docs/v4/reference/ipiechartevents/
*/
chart.events.on('inited', function(event) {
// populate our custom legend when chart renders
chart.customLegend = document.getElementById('legend');
// https://www.amcharts.com/docs/v4/tutorials/truncating-legend-labels/
//chart.customLegend.labels.template.truncate = true;
for (var i in chart.data) {
var row = chart.data[i];
var color = chart.data[i].color;
var name = row.name;
chart.customLegend.innerHTML +=
[
'<div class="legend-item" id="legend-item-' + i + '" style="color: ' + color + ';">',
'<div class="legend-marker" style="background: ' + color + '"></div>',
name,
'</div>'
].join("");
}
});
})()
I found this example: https://codepen.io/team/amcharts/pen/PQrvJr where you can see that the "netherland" has a different color between the 2 levels, but there is nothing specific in the javascript code...
Do you know if it's possible ?
I found this example: https://codepen.io/team/amcharts/pen/PQrvJr where you can see that the "netherland" has a different color between the 2 levels, but there is nothing specific in the javascript code...
What's making that happen is:
pieSeries.colors.step = 2;
The step
property of a ColorSet
causes it to skip colors in its list (in this case, auto-generated). If you compare every 2nd color of the outer series to the inner ones you'll see those coincide.
As for coloring a specific slice, there are different ways to go about it.
Right now this is how the Pie Series are getting their colors:
// Earlier in code
var colorSet = new am4core.ColorSet();
colorSet.list = ["#18dc08", "#e2ed0c", "#3be791", "#0eade6", "#8f55e9", "#dd0a4b"].map(function(color) {
return new am4core.color(color);
});
// createPie() ...
pieSeries.colors = colorSet;
If you know precisely which slice in which series you want to change you can provide a new ColorSet
whose list is similar but adjusted for that one slice, e.g.:
if (chart.series.length === 3) {
var distinctColors = new am4core.ColorSet();
distinctColors.list = colorSet.list.map(function(color, index) {
if (index === 1) {
return am4core.color("gray");
}
return color;
});
pieSeries.colors = distinctColors;
} else {
pieSeries.colors = colorSet;
}
Ideally, though, you'd use an adapter, so whenever a fill
is about to be applied, you can supply logic to determine what color to provide, e.g. coloring Sector1: categor3 as black (semi-opaque, though, due to other stuff in the code):
pieSeries.slices.template.adapter.add("fill", function(fill, target) {
if (target.dataItem.dataContext && target.dataItem.dataContext.name === "Sector1" && targetAttribute === "category3") {
return am4core.color("black");
}
return fill;
});
Here's a demo (I also replaced your "over"
event code with an adapter for tooltipHTML
):