JSON to Pie Chart - Educational Guide
Learn how to visualize JSON data as an SVG pie chart using pure JavaScript. No external charting libraries required—just HTML, CSS, and a bit of math.
Objective
- Understand the geometry behind pie chart slices
- Parse a JSON array of objects with
labelandvalueproperties - Generate SVG arcs dynamically and add a legend
- Provide an interactive preview with copy-ready code
Coding Section
This example takes a JSON array and renders each item as a slice of a pie chart, sized proportionally by value.
1. HTML Structure
We need a textarea for JSON input and a container for the SVG chart plus legend.
<section class="demo-card">
<h4>JSON Input</h4>
<textarea id="jsonInput" rows="10"></textarea>
<div class="demo-actions">
<button id="renderBtn">Render Chart</button>
<button id="resetBtn">Reset Sample</button>
</div>
</section>
<section class="demo-card">
<h4>Pie Chart Output</h4>
<div id="chartOutput" class="demo-output">
<svg id="pieCanvas" viewBox="0 0 200 200"></svg>
<ul id="legend" class="legend-list"></ul>
</div>
<div id="errorOutput"></div>
</section>
2. CSS Styling
Basic styles keep the chart centered and the legend readable.
.demo-output {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
align-items: flex-start;
justify-content: center;
}
#pieCanvas {
max-width: 260px;
max-height: 260px;
}
.legend-list {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
gap: 6px;
}
.legend-item {
display: flex;
align-items: center;
gap: 8px;
font-size: 0.9rem;
}
.legend-dot {
width: 12px;
height: 12px;
border-radius: 3px;
}
.legend-pct {
color: #888;
font-size: 0.85rem;
margin-left: auto;
}
3. JavaScript - The Geometry
Each slice is an SVG arc. We convert percentages into start/end angles and use trigonometry to draw paths.
const COLORS = [
"#3b82f6", "#ef4444", "#f59e0b", "#10b981",
"#8b5cf6", "#f97316", "#06b6d4", "#ec4899"
];
// Convert angle in degrees to x,y on circle
function polarToXY(cx, cy, r, angleDeg) {
const rad = (angleDeg - 90) * Math.PI / 180;
return [cx + r * Math.cos(rad), cy + r * Math.sin(rad)];
}
// Build an SVG arc path string
function describeArc(cx, cy, r, startAngle, endAngle) {
const [x1, y1] = polarToXY(cx, cy, r, startAngle);
const [x2, y2] = polarToXY(cx, cy, r, endAngle);
const largeArc = (endAngle - startAngle) > 180 ? 1 : 0;
return [
`M ${cx} ${cy}`, // move to center
`L ${x1} ${y1}`, // line to arc start
`A ${r} ${r} 0 ${largeArc} 1 ${x2} ${y2}`, // arc
"Z" // close path
].join(" ");
}
4. JavaScript - Rendering the Chart
Loop through the data, calculate each slice's angle, and append SVG paths.
function renderPie(data) {
const svg = document.getElementById("pieCanvas");
const legend = document.getElementById("legend");
svg.innerHTML = "";
legend.innerHTML = "";
const total = data.reduce((sum, d) => sum + d.value, 0);
if (total === 0) return;
const CX = 100, CY = 100, R = 90;
let startAngle = 0;
data.forEach((item, i) => {
const pct = item.value / total;
const endAngle = startAngle + pct * 360;
const color = COLORS[i % COLORS.length];
// Create slice
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
path.setAttribute("d", describeArc(CX, CY, R, startAngle, endAngle));
path.setAttribute("fill", color);
svg.appendChild(path);
// Create legend item
const li = document.createElement("li");
li.className = "legend-item";
li.innerHTML = `
<span class="legend-dot" style="background:${color}"></span>
<span>${item.label}</span>
<span class="legend-pct">${(pct * 100).toFixed(1)}%</span>
`;
legend.appendChild(li);
startAngle = endAngle;
});
}
5. Complete Flow
Wire up the button, parse JSON, and call the renderer.
const sampleData = [
{ label: "Electronics", value: 42000 },
{ label: "Clothing", value: 28500 },
{ label: "Home & Garden", value: 19800 },
{ label: "Sports", value: 14200 }
];
const input = document.getElementById("jsonInput");
input.value = JSON.stringify(sampleData, null, 2);
renderPie(sampleData);
document.getElementById("renderBtn").addEventListener("click", () => {
try {
const parsed = JSON.parse(input.value);
renderPie(parsed);
} catch (err) {
document.getElementById("errorOutput").innerHTML =
`<div class="demo-error">${err.message}</div>`;
}
});
document.getElementById("resetBtn").addEventListener("click", () => {
input.value = JSON.stringify(sampleData, null, 2);
renderPie(sampleData);
});
Preview Section
Paste JSON in the input area and render it as a pie chart.