Skip to content

Instantly share code, notes, and snippets.

@tangoabcdelta
Created April 29, 2026 01:23
Show Gist options
  • Select an option

  • Save tangoabcdelta/bd624036f2c29803bd2245c86fa90a84 to your computer and use it in GitHub Desktop.

Select an option

Save tangoabcdelta/bd624036f2c29803bd2245c86fa90a84 to your computer and use it in GitHub Desktop.
D3.js Marimekko chart template
<script>
fetch("data.json")
.then(response => response.json())
.then(json => {
// Filter only "Electronic Technology" stocks
const data = json.data
.filter(d => d.d[21] === "Electronic Technology")
.map(d => ({
symbol: d.s,
company: d.d[27],
marketCap: d.d[15]
}));
const width = 900;
const height = 500;
const svg = d3.select("#marimekko")
.attr("viewBox", `0 0 ${width} ${height}`)
.attr("preserveAspectRatio", "xMidYMid meet");
// Total market cap of Electronic Technology stocks
const totalCap = d3.sum(data, d => d.marketCap);
// Decide how tall each rectangle should be (e.g. 50px)
const rectHeight = 50;
let x = 0;
let y = 0;
data.forEach((d, i) => {
const rectWidth = (d.marketCap / totalCap) * width;
// Wrap to next row if exceeding chart width
if (x + rectWidth > width) {
x = 0;
y += rectHeight;
}
// Draw rectangle tile
svg.append("rect")
.attr("class", "tile")
.attr("x", x)
.attr("y", y)
.attr("width", rectWidth)
.attr("height", rectHeight)
.attr("fill", d3.schemeCategory10[i % 10]);
// Label inside rectangle
svg.append("text")
.attr("class", "label")
.attr("x", x + rectWidth / 2)
.attr("y", y + rectHeight / 2)
.attr("text-anchor", "middle")
.attr("dy", ".35em")
.text(d.symbol);
x += rectWidth;
});
})
.catch(error => console.error("Error loading JSON:", error));
</script>
<!DOCTYPE html>
<meta charset="utf-8">
<html>
<head>
<title>D3.js Marimekko Chart</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
body {
font-family: sans-serif;
}
.tile {
stroke: #fff;
stroke-width: 1px;
}
.label {
font-size: 12px;
fill: #333;
pointer-events: none;
}
svg {
width: 100%;
height: auto;
}
</style>
</head>
<body>
<svg id="marimekko"></svg>
<script>
// Replace this with your uploaded JSON data
const data = [
{ category: "A", subcategory: "X", value: 30 },
{ category: "A", subcategory: "Y", value: 20 },
{ category: "B", subcategory: "X", value: 25 },
{ category: "B", subcategory: "Y", value: 25 }
];
const width = 800;
const height = 400;
const svg = d3.select("#marimekko")
.attr("viewBox", `0 0 ${width} ${height}`)
.attr("preserveAspectRatio", "xMidYMid meet");
// Aggregate totals by category
const categories = d3.rollups(data, v => d3.sum(v, d => d.value), d => d.category);
const total = d3.sum(categories, d => d[1]);
let x = 0;
categories.forEach(([cat, catTotal]) => {
const catWidth = (catTotal / total) * width;
let y = 0;
const subcats = data.filter(d => d.category === cat);
const subTotal = d3.sum(subcats, d => d.value);
subcats.forEach(d => {
const rectHeight = (d.value / subTotal) * height;
svg.append("rect")
.attr("class", "tile")
.attr("x", x)
.attr("y", y)
.attr("width", catWidth)
.attr("height", rectHeight)
.attr("fill", d3.schemeCategory10[subcats.indexOf(d)]);
svg.append("text")
.attr("class", "label")
.attr("x", x + catWidth / 2)
.attr("y", y + rectHeight / 2)
.attr("text-anchor", "middle")
.attr("dy", ".35em")
.text(`${cat}-${d.subcategory}`);
y += rectHeight;
});
x += catWidth;
});
</script>
</body>
</html>

🔑 Key Points

  • Responsive design: The viewBox and preserveAspectRatio attributes make the chart scale across devices.
  • Data binding: Replace the data array with your JSON structure.
  • Category widths: Each category’s width is proportional to its total value.
  • Subcategory heights: Within each category, rectangles are stacked vertically by relative value.

👉 If your JSON has a different structure (e.g., nested objects or arrays), I can help you adapt the parsing logic. Would you like me to adjust this code to match the exact schema of your uploaded JSON?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment