A donut with a fine grain over soft gradients, rounded slices and shadows that deepen on hover. A printed, tactile look instead of flat color.
Grain and gradients don’t change what the chart says; they change how it feels. They suit pages where the chart is part of the design, and they print well on posters. On a busy dashboard, flat color is easier on the eye.
Built with amCharts 5, a JavaScript library. The JavaScript includes your theme and renderer (canvas or SVG); the JSON also follows the changes you make with the controls.
npm install @amcharts/amcharts5. See Getting started.
The same chart as a JSON config. Chart Maker reads and writes this format, the library's JSON parser turns it into a chart, and the <am5-chart> element puts it on a page with no code."type" is the class to create and "settings" what you would pass to its new() in code; "properties" fill in its parts, lists such as series and axes or templates such as columns.template; "refs" holds objects used in more than one place ("#series-0" stands for the one named series-0); a string starting with "@" takes a value from another object, such as "@series.get('fill')".
A complete page. Save it as an .html file and open it in a browser.
Paste this into an AI coding assistant to build the chart from scratch. More in amCharts & AI.
// Create root element
// https://www.amcharts.com/docs/v5/getting-started/#Root_element
var root = am5.Root.new("chartdiv");
// Set themes
// https://www.amcharts.com/docs/v5/concepts/themes/
root.setThemes([
am5themes_Animated.new(root),
am5themes_Responsive.new(root)
]);
// Create chart
// https://www.amcharts.com/docs/v5/charts/percent-charts/pie-chart/
var chart = root.container.children.push(
am5percent.PieChart.new(root, {
endAngle: 270, // a full circle, from the top round to the top again
layout:root.verticalLayout, // the legend goes below the donut
innerRadius: am5.percent(60) // a hole 60% of the radius turns the pie into a donut
})
);
// Create series
// https://www.amcharts.com/docs/v5/charts/percent-charts/pie-chart/#Series
var series = chart.series.push(
am5percent.PieSeries.new(root, {
valueField: "value",
categoryField: "category",
endAngle: 270 // the slices fill the whole ring
})
);
// each slice darkens from its own color at the outer edge towards the center of the pie
var gradient = am5.RadialGradient.new(root, {
stops: [
{ color: am5.color(0x000000) },
{ color: am5.color(0x000000) },
{}
]
})
series.slices.template.setAll({
fillGradient: gradient,
strokeWidth: 2, // 2px...
stroke: root.interfaceColors.get("background"), // ...lines in the background color between the slices
cornerRadius: 10, // rounded slice corners
shadowOpacity: 0.1, // a faint shadow...
shadowOffsetX: 2, // ...2px to the right...
shadowOffsetY: 2, // ...and 2px down
shadowColor: am5.color(0x000000),
fillPattern: am5.GrainPattern.new(root, { // grain: random black specks over the gradient
maxOpacity: 0.2, // each speck at most 20% opaque
density: 0.5, // about half the pixels get a speck
colors: [am5.color(0x000000)]
})
})
// under the pointer, a slice's shadow darkens and spreads
series.slices.template.states.create("hover", {
shadowOpacity: 1,
shadowBlur: 10
})
series.ticks.template.setAll({
strokeOpacity:0.4, // faint...
strokeDasharray:[2,2] // ...dotted tick lines
})
// hidden, the ring closes up at the top (-90 degrees), so on load it opens clockwise
series.states.create("hidden", {
endAngle: -90
});
// Set data
// https://www.amcharts.com/docs/v5/charts/percent-charts/pie-chart/#Setting_data
series.data.setAll([{
category: "Lithuania",
value: 500
}, {
category: "Czechia",
value: 300
}, {
category: "Ireland",
value: 200
}, {
category: "Germany",
value: 100
}]);
var legend = chart.children.push(am5.Legend.new(root, {
centerX: am5.percent(50), // the legend's middle...
x: am5.percent(50), // ...at the middle of the chart
marginTop: 15, // 15px of space above...
marginBottom: 15, // ...and below the legend
}));
// legend markers show plain colors, without the slices' gradient
legend.markerRectangles.template.adapters.add("fillGradient", function() {
return undefined;
})
legend.data.setAll(series.dataItems);
series.appear(1000, 100);
{
"type": "PieChart",
"settings": {
"endAngle": 270,
"layout": {
"type": "VerticalLayout"
},
"innerRadius": {
"type": "Percent",
"value": 60
}
},
"properties": {
"series": [
"#series-0"
]
},
"children": [
{
"type": "Legend",
"settings": {
"centerX": {
"type": "Percent",
"value": 50
},
"x": {
"type": "Percent",
"value": 50
},
"marginTop": 15,
"marginBottom": 15
},
"properties": {
"data": "#series-0.dataItems"
}
}
],
"refs": [
{
"data-0": [
{
"category": "Lithuania",
"value": 500
},
{
"category": "Czechia",
"value": 300
},
{
"category": "Ireland",
"value": 200
},
{
"category": "Germany",
"value": 100
}
]
},
{
"series-0": {
"type": "PieSeries",
"settings": {
"valueField": "value",
"categoryField": "category",
"endAngle": 270
},
"states": [
{
"key": "hidden",
"settings": {
"endAngle": -90
}
}
],
"properties": {
"data": "#data-0",
"slices": {
"properties": {
"template": {
"settings": {
"fillGradient": {
"type": "RadialGradient",
"settings": {
"stops": [
{
"color": {
"type": "Color",
"value": "#000000"
},
"opacityInherited": true
},
{
"color": {
"type": "Color",
"value": "#000000"
},
"opacityInherited": true
},
{
"color": {
"type": "Color",
"value": "#8067dc"
},
"colorInherited": true,
"opacityInherited": true
}
]
}
},
"strokeWidth": 2,
"stroke": "@root.interfaceColors.get('background')",
"cornerRadius": 10,
"shadowOpacity": 0.1,
"shadowOffsetX": 2,
"shadowOffsetY": 2,
"shadowColor": {
"type": "Color",
"value": "#000000"
},
"fillPattern": {
"type": "GrainPattern",
"settings": {
"maxOpacity": 0.2,
"density": 0.5,
"colors": [
{
"type": "Color",
"value": "#000000"
}
]
}
}
},
"states": [
{
"key": "hover",
"settings": {
"shadowOpacity": 1,
"shadowBlur": 10
}
}
]
}
}
},
"ticks": {
"properties": {
"template": {
"settings": {
"strokeOpacity": 0.4,
"strokeDasharray": [
2,
2
]
}
}
}
}
}
}
}
]
}