Skip to content

Instantly share code, notes, and snippets.

@Chi-Loong
Last active March 17, 2021 07:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Chi-Loong/e3389dfb6873c85caf445f0faba52ec4 to your computer and use it in GitHub Desktop.
Save Chi-Loong/e3389dfb6873c85caf445f0faba52ec4 to your computer and use it in GitHub Desktop.
D3 bar chart part II

Extension of D3 bar chart for teaching and explanation purposes.

Follow's D3 design pattern of enter, update and exit loop with simple transition to show how this can be done easily. Updated to D3 v6, using the selection.join syntax.

Part 2 of a series.

Part 1 here

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
.svgRect {
stroke: none;
fill: #f00;
}
</style>
</head>
<body>
<button id="bt1">Subject 1</button>
<button id="bt2">Subject 2</button>
<svg id="chart" viewBox="0 0 960 500"></svg>
<script src="https://d3js.org/d3.v6.min.js"></script>
<script>
let data = [
{student: "Alfred", score: 65},
{student: "Bernard", score: 35},
{student: "Christine", score: 75}
];
let data2 = [
{student: "Alfred", score: 25},
{student: "Bernard", score: 95},
{student: "Christine", score: 65},
{student: "Daniella", score: 40},
{student: "Eric", score: 50}
];
let margin = {top: 20, right: 20, bottom: 40, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
let chart = d3.select("#chart")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Add scales
let xScale = d3.scaleBand()
.domain(data.map(function(d) { return d.student; }))
.rangeRound([0, width])
.padding(0.1);
let yScale = d3.scaleLinear()
.domain([0, 100])
.rangeRound([height, 0]);
// Add x-axis
chart.append("g")
.attr("class", "axis axis-x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale));
// Add y-axis
chart.append("g")
.attr("class", "axis axis-y")
.call(d3.axisLeft(yScale).ticks(10));
//Sample enter, update and exit loop
function drawChart(dataSet) {
//xScale domain needs to change based on data set
xScale.domain(dataSet.map(function(d) { return d.student; }));
chart.select("g .axis-x")
.transition()
.duration(1000)
.call(d3.axisBottom(xScale));
chart.selectAll("rect")
.data(dataSet)
.join(
enter => enter
.append("rect")
.attr("x", d => xScale(d.student))
.attr("y", d => yScale(d.score))
.attr("width", 0)
.attr("height", 0)
.attr("class", "svgRect")
.call(enter => enter.transition()
.duration(1000)
.attr("width", xScale.bandwidth())
.attr("height", d => height - yScale(d.score))
),
update => update
.call(update => update.transition()
.duration(1000)
.attr("x", d => xScale(d.student))
.attr("y", d => yScale(d.score))
.attr("width", xScale.bandwidth())
.attr("height", d => height - yScale(d.score))
),
exit => exit
.call(exit => exit.transition()
.duration(1000)
.attr("width", 0)
.attr("height", 0)
.remove()
)
);
}
d3.select("#bt1").on("click", function() {
drawChart(data);
});
d3.select("#bt2").on("click", function() {
drawChart(data2);
});
drawChart(data);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment