Skip to content

Instantly share code, notes, and snippets.

@LemoNode
Last active November 13, 2018 18:00
Show Gist options
  • Save LemoNode/e4016644ceb78d1460fde164f89c491a to your computer and use it in GitHub Desktop.
Save LemoNode/e4016644ceb78d1460fde164f89c491a to your computer and use it in GitHub Desktop.
Pyramid chart
license: gpl-3.0
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v5.min.js"></script>
<style>
body {
padding-top: 45px;
margin: auto;
width: 650px;
font: 11px arial;
}
.hide path,
.hide line {
display: none;
}
</style>
</head>
<body>
<svg id="chart" width="650" height="420"></svg>
<select id="options"></select>
<script>
var server = [
{age: "17 - 19", m_1: 54, f_1: 32, m_2: 44, f_2: 132, m_3: 41, f_3: 21},
{age: "20 - 24", m_1: 62, f_1: 62, m_2: 14, f_2: 102, m_3: 55, f_3: 25},
{age: "25 - 29", m_1: 32, f_1: 52, m_2: 10, f_2: 92, m_3: 45, f_3: 20},
{age: "30 - 34", m_1: 30, f_1: 46, m_2: 9, f_2: 83, m_3: 40, f_3: 18},
{age: "35 - 39", m_1: 26, f_1: 42, m_2: 5, f_2: 63, m_3: 35, f_3: 13},
{age: "40 - 44", m_1: 22, f_1: 40, m_2: 6, f_2: 57, m_3: 30, f_3: 10},
{age: "45 - 49", m_1: 14, f_1: 32, m_2: 2, f_2: 52, m_3: 20, f_3: 5},
{age: "50 +", m_1: 10, f_1: 22, m_2: 2, f_2: 42, m_3: 18, f_3: 3},
];
load(server);
function load(data) {
var total = Object.keys(data[0]).slice(1)
var allM = [...total].filter(f => f.includes("m"))
var allF = [...total].filter(f => f.includes("f"))
var options = d3.select("#options").selectAll("option")
.data(allM)
.enter().append("option")
.attr("value", d => d.split("m")[1])
.text(d => "Type: " + d.split("_")[1])
data.forEach(function(d) {
var m = 0, f = 0;
for (var i = 0; i < allM.length; i++) {
m += d[allM[i]], f += d[allF[i]];
}
d.m = m;
d.f = f;
return d;
})
chart(data, total);
};
function chart(data, team) {
var svg = d3.select("#chart"),
margin = {top: 15, right: 10, bottom: 15, left: 10, axis: 25},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var xM = d3.scaleLinear()
.rangeRound([(width / 2) + margin.axis, width - margin.left])
.domain([0, d3.max(data, d => Math.max(d.m, d.f))]).nice()
var xF = d3.scaleLinear()
.rangeRound([(width / 2) - margin.axis, margin.right])
.domain(xM.domain());
var y = d3.scaleBand()
.domain([...new Set(data.map(d => d.age))])
.rangeRound([height - margin.bottom, margin.top])
.padding(0.1);
var xAxisM = svg.append("g")
.attr("class", "x-axis")
.attr("transform", `translate(0,${(height - margin.bottom)})`)
.call(d3.axisBottom(xM));
var xAxisF = xAxisM.clone().call(d3.axisBottom(xF));
var yAxis = svg.append("g")
.attr("class", "hide")
.style("text-anchor", "middle")
.attr("transform",
`translate(${((margin.left + width + margin.right) / 2)}, 0)`)
.call(d3.axisLeft(y).ticks(null, "s"))
var male = svg.selectAll(null)
.data(data)
.enter().append("rect")
.attr("opacity", .75)
.attr("fill","steelblue")
.attr("x", xM(0))
.attr("y", d => y(d.age))
.attr("height", y.bandwidth())
.attr("width", d => xM(d.m) - xM(0));
var female = svg.selectAll(null)
.data(data)
.enter().append("rect")
.attr("opacity", .75)
.attr("fill","darkorange")
.attr("x", d => xF(d.f))
.attr("y", d => y(d.age))
.attr("height", y.bandwidth())
.attr("width", d => Math.abs(xF(d.f) - xF(0)));
update(d3.select("#options").property("value"), 0);
function update(input, speed) {
var maleInput = svg.selectAll(".maleInput")
.data(data, d => d.age);
maleInput.exit().remove()
maleInput.enter().append("rect")
.attr("class", "maleInput")
.attr("fill","steelblue")
.attr("x", xM(0))
.attr("y", d => y(d.age))
.attr("height", y.bandwidth())
.merge(maleInput)
.transition().duration(speed)
.attr("width", d => xM(d["m" + input]) - xM(0));
var femaleInput = svg.selectAll(".femaleInput")
.data(data, d => d.age);
femaleInput.exit().remove()
femaleInput.enter().append("rect")
.attr("class", "femaleInput")
.attr("fill","darkorange")
.attr("y", d => y(d.age))
.attr("height", y.bandwidth())
.merge(femaleInput)
.transition().duration(speed)
.attr("x", d => xF(d["f" + input]))
.attr("width", d => Math.abs(xF(d["f" + input]) - xF(0)));
}
var select = d3.select("#options")
.on("change", function() {
update(this.value, 750)
})
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment