D3.js - Working Example
D3.js - Working Example: Animated Bar Chart
Section titled “D3.js - Working Example: Animated Bar Chart”This chapter demonstrates how to combine several D3.js concepts to create an animated bar chart. We’ll use a sample dataset, load it, and then render a bar chart with mouseover interactions and entry animations.
First, create a population-data.csv file (if you don’t have it from a previous chapter):
year,population2006,402008,452010,482012,512014,532016,572017,62Now, let’s build the bar chart step by step in an HTML file.
Step 1: HTML Structure and Basic Styles
Section titled “Step 1: HTML Structure and Basic Styles”<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>D3 Animated Bar Chart</title> <script src="https://d3js.org/d3.v7.min.js"></script> <style> body { font-family: Arial, sans-serif; } .bar { fill: steelblue; transition: fill 0.2s ease-out; } .bar:hover, .bar.highlight { fill: orange; } .chart-title { font-size: 18px; font-weight: bold; text-anchor: middle; } .axis-label { font-size: 12px; text-anchor: middle; } .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; } .axis text { font-family: sans-serif; font-size: 10px; } .tooltip { position: absolute; text-align: center; padding: 8px; font: 12px sans-serif; background: lightsteelblue; border: 0px; border-radius: 8px; pointer-events: none; /* crucial for mouse events on bars */ opacity: 0; } </style></head><body> <div id="chart-container"></div> <script> // D3 code follows </script></body></html>Step 2: Setup SVG, Margins, and Dimensions
Section titled “Step 2: Setup SVG, Margins, and Dimensions”const container = d3.select("#chart-container");
const margin = {top: 60, right: 30, bottom: 70, left: 70};const width = 600 - margin.left - margin.right;const height = 400 - margin.top - margin.bottom;
const svg = container.append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", `translate(${margin.left},${margin.top})`);
// Tooltip divconst tooltip = d3.select("body").append("div") .attr("class", "tooltip");Step 3: Define Scales
Section titled “Step 3: Define Scales”d3.scaleBand() for the X-axis (years, categorical) and d3.scaleLinear() for the Y-axis (population, quantitative).
const xScale = d3.scaleBand() .range([0, width]) .padding(0.2); // Padding between bars
const yScale = d3.scaleLinear() .range([height, 0]); // Y-axis is inverted (0 at top)Step 4: Load and Process Data
Section titled “Step 4: Load and Process Data”d3.csv("population-data.csv", d => { // Convert data types return { year: d.year, // Keep year as string for scaleBand population: +d.population // Convert population to number };}).then(data => { // Check data console.log(data);
// Update scale domains based on data xScale.domain(data.map(d => d.year)); yScale.domain([0, d3.max(data, d => d.population)]);
// Call function to draw chart elements (defined next) drawChart(data);
}).catch(error => { console.error("Error loading or processing data:", error); container.text("Failed to load data for the chart.");});Step 5: Draw Chart Elements (Axes and Bars)
Section titled “Step 5: Draw Chart Elements (Axes and Bars)”function drawChart(data) { // Add X-axis svg.append("g") .attr("class", "axis x-axis") .attr("transform", `translate(0,${height})`) .call(d3.axisBottom(xScale)) .selectAll("text") .style("text-anchor", "end") .attr("dx", "-.8em") .attr("dy", ".15em") .attr("transform", "rotate(-45)");
// Add Y-axis svg.append("g") .attr("class", "axis y-axis") .call(d3.axisLeft(yScale));
// Add Bars with entry animation svg.selectAll(".bar") .data(data) .join("rect") .attr("class", "bar") .attr("x", d => xScale(d.year)) .attr("width", xScale.bandwidth()) .attr("y", d => yScale(0)) // Start from y=0 for animation .attr("height", 0) // Start with height=0 for animation .on("mouseover", handleMouseOver) .on("mouseout", handleMouseOut) .transition() .duration(800) .ease(d3.easeBounceOut) // A fun easing function .delay((d, i) => i * 100) // Stagger the animation .attr("y", d => yScale(d.population)) .attr("height", d => height - yScale(d.population));
// Add Chart Title svg.append("text") .attr("class", "chart-title") .attr("x", width / 2) .attr("y", 0 - (margin.top / 2)) .text("Population Growth Over Years");
// Add X-axis Label svg.append("text") .attr("class", "axis-label") .attr("x", width / 2) .attr("y", height + margin.bottom * 0.8) .text("Year");
// Add Y-axis Label svg.append("text") .attr("class", "axis-label") .attr("transform", "rotate(-90)") .attr("y", 0 - margin.left * 0.8) .attr("x", 0 - (height / 2)) .text("Population (in millions, fictional)");}Step 6: Mouse Event Handlers for Tooltip and Highlight
Section titled “Step 6: Mouse Event Handlers for Tooltip and Highlight”function handleMouseOver(event, d) { d3.select(this).classed("highlight", true);
tooltip.transition() .duration(200) .style("opacity", .9); tooltip.html(`Year: ${d.year}<br/>Population: ${d.population}M`) .style("left", (event.pageX + 5) + "px") .style("top", (event.pageY - 28) + "px");}
function handleMouseOut(event, d) { d3.select(this).classed("highlight", false);
tooltip.transition() .duration(500) .style("opacity", 0);}Place all the JavaScript code within the <script> tags in your HTML file. When you open it in a browser, you should see a bar chart. Bars will animate into place, and hovering over a bar will highlight it and show a tooltip with its data.
Key Concepts Illustrated
Section titled “Key Concepts Illustrated”- Modular Structure: Separating concerns like setup, data loading, and drawing.
- Margins and SVG Grouping: Using the D3 margin convention for layout.
- Scales:
d3.scaleBandfor categorical data on the X-axis,d3.scaleLinearfor quantitative data on the Y-axis. - Axes: Generating axes with
d3.axisBottomandd3.axisLeft. - Data Loading (
d3.csv): Fetching and parsing CSV data asynchronously. - Data Join (
selection.join): Creating bars based on data. - Transitions and Easings: Animating the bars on entry (
.transition(),.duration(),.ease(),.delay()). - Event Handling: Using
.on("mouseover", ...)and.on("mouseout", ...)for interactivity. - Tooltips: Creating a simple HTML div tooltip that follows the mouse.
This example provides a solid template. You can further enhance it by adding features like sorting, filtering, or updating the chart with new data.