How to Build an Interactive Radial Bar Chart for Your KPI Dashboard
You’ve probably seen those sleek circular charts on a few high‑end dashboards and thought, “That would look great for my metrics.” The truth is, radial bar charts can turn boring numbers into a visual story that’s easy to scan at a glance. In a world where every second counts, a quick glance at a circle can tell you if sales are up, if churn is down, or if a campaign is on fire. Let’s walk through a simple, step‑by‑step process to create an interactive radial bar chart that you can drop into any KPI dashboard.
Why Choose a Radial Bar?
Most people are used to straight bars or line graphs. A radial bar flips the script by wrapping the bars around a circle. This does two things:
- Space Efficiency – You can fit many KPIs in a compact, eye‑catching shape.
- Immediate Impact – The length of each arc is instantly visible, especially when you add color or animation.
At Circular Insights we love anything that makes data feel alive, and radial bars are perfect for that. They’re not just pretty; they’re practical when you need to compare several metrics side by side.
Tools You’ll Need
Before we dive into the steps, let’s pick the right toolbox. I prefer JavaScript because it runs in any browser and works well with most dashboard platforms.
- D3.js – The gold standard for custom visualizations.
- Chart.js with the chartjs-plugin-doughnutlabel – Simpler, good for quick prototypes.
- Plotly.js – Great if you want built‑in interactivity without writing a lot of code.
Pick one that matches your comfort level. I’ll use D3 for the walkthrough because it gives full control over the look and feel.
Step 1: Set Up Your Project
Create a new folder and add three files:
index.html
style.css
script.js
In index.html include the D3 library from a CDN:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Radial KPI Chart</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<svg id="radialChart"></svg>
<script src="https://d3js.org/d3.v7.min.js"></script>
<script src="script.js"></script>
</body>
</html>
That’s all the boilerplate you need. Keep the HTML minimal – the magic happens in the script.
Step 2: Prepare Your KPI Data
A radial bar works best with a list of values and a label for each. For example:
const kpis = [
{ name: "Revenue", value: 78, color: "#4caf50" },
{ name: "Growth", value: 55, color: "#2196f3" },
{ name: "Churn", value: 20, color: "#f44336" },
{ name: "Engagement",value: 90, color: "#ff9800" }
];
The value should be a percentage (0‑100). If your raw numbers are in dollars or units, convert them to a percentage of the target you set for that KPI. This keeps the chart consistent and easy to read.
Step 3: Define the Geometry
Radial bars need a few measurements:
- Inner radius – Where the first bar starts.
- Bar thickness – How wide each arc is.
- Gap – Space between arcs.
Add these constants to script.js:
const width = 400;
const height = 400;
const innerRadius = 80;
const barThickness = 30;
const gap = 5;
Create an SVG canvas that matches the size:
const svg = d3.select("#radialChart")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", `translate(${width/2},${height/2})`);
The translate moves the origin to the center of the circle, making it easier to draw arcs.
Step 4: Build the Scale
We need a scale that maps a percentage (0‑100) to an angle (0‑2π radians). D3’s scaleLinear does the job:
const angleScale = d3.scaleLinear()
.domain([0, 100])
.range([0, 2 * Math.PI]);
Now each KPI’s value can be turned into an angle for the arc.
Step 5: Draw the Arcs
D3’s arc generator creates the path data for each bar. Loop through the KPI array and draw each arc:
kpis.forEach((d, i) => {
const radius = innerRadius + i * (barThickness + gap);
const arc = d3.arc()
.innerRadius(radius)
.outerRadius(radius + barThickness)
.startAngle(0)
.endAngle(angleScale(d.value));
svg.append("path")
.attr("d", arc)
.attr("fill", d.color)
.attr("stroke", "#fff")
.attr("stroke-width", 1);
});
Each iteration moves the next bar outward, leaving a small gap for visual separation. The stroke adds a thin white line so the arcs don’t blend together.
Step 6: Add Labels
A chart is only useful if the viewer knows what each bar means. Place a label at the end of each arc:
kpis.forEach((d, i) => {
const radius = innerRadius + i * (barThickness + gap) + barThickness / 2;
const angle = angleScale(d.value);
const x = Math.cos(angle - Math.PI/2) * radius;
const y = Math.sin(angle - Math.PI/2) * radius;
svg.append("text")
.attr("x", x)
.attr("y", y)
.attr("dy", "0.35em")
.attr("text-anchor", angle > Math.PI ? "end" : "start")
.style("font-family", "sans-serif")
.style("font-size", "12px")
.text(`${d.name}: ${d.value}%`);
});
The math rotates the label so it sits just outside the bar, following the curve. Adjust font-size in style.css if you need larger text.
Step 7: Make It Interactive
Interactivity is what turns a static chart into a dashboard widget. Let’s add a simple hover effect that highlights the bar and shows a tooltip.
First, create a tooltip element in index.html:
<div id="tooltip" style="position:absolute; padding:5px; background:#333; color:#fff; border-radius:3px; pointer-events:none; opacity:0;"></div>
Then, in script.js, add mouse events:
const tooltip = d3.select("#tooltip");
svg.selectAll("path")
.on("mouseover", function(event, d) {
d3.select(this).attr("fill", d3.rgb(d3.select(this).attr("fill")).brighter(0.5));
tooltip.style("opacity", 1)
.html(`${d.name}<br/>${d.value}%`)
.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 20) + "px");
})
.on("mouseout", function(event, d) {
d3.select(this).attr("fill", d3.select(this).attr("fill"));
tooltip.style("opacity", 0);
});
When the user hovers over a bar, the color brightens and a small box appears with the KPI name and exact value. You can expand this to include trend arrows, last‑month comparison, or a link to a deeper drill‑down view.
Step 8: Polish the Look
A few finishing touches make the chart feel professional:
- Add a background circle to give a subtle frame.
- Use a subtle gradient on each bar for depth.
- Animate the arcs on load so they sweep from 0 to their final angle.
Here’s a quick animation snippet:
svg.selectAll("path")
.attr("stroke-dasharray", function() { return this.getTotalLength(); })
.attr("stroke-dashoffset", function() { return this.getTotalLength(); })
.transition()
.duration(1200)
.attr("stroke-dashoffset", 0);
The stroke-dasharray trick makes the bars draw themselves like a clock hand. Adjust duration for faster or slower animation.
Step 9: Plug Into Your Dashboard
Now that the chart lives in an SVG, you can embed it anywhere: a web page, a Power BI custom visual, or a Tableau extension that supports HTML. If you’re using a framework like React or Vue, just wrap the D3 code in a component and pass the KPI data as props.
Remember to keep the data source dynamic. Pull the latest numbers from your analytics API and call a renderChart() function each time the data updates. That way the radial bars stay fresh without a page reload.
Step 10: Test on Real Devices
A radial chart looks great on a desktop, but does it work on a phone? Test the SVG at different widths and make sure the text doesn’t overlap. You can add a simple media query in style.css to shrink the SVG on small screens:
@media (max-width: 600px) {
svg { width: 300px; height: 300px; }
}
If you need more space for labels, consider showing only the KPI name inside the circle and moving the exact value to the tooltip.
That’s it! With these ten steps you have a fully interactive radial bar chart ready to sit alongside your other KPIs. The best part is that you can tweak colors, thickness, and animation to match any brand style. At Circular Insights we love turning raw numbers into circles that tell a story at a glance. Give it a try, and let the data spin its way into your next dashboard.