JavaScript D3.js

Data-Driven Documents for powerful data visualizations

🎯 What is D3.js?

D3.js (Data-Driven Documents) is a powerful JavaScript library for creating dynamic, interactive data visualizations using web standards like HTML, SVG, and CSS. It gives you complete control over the final result.


<!-- Include D3.js -->
<script src="https://d3js.org/d3.v7.min.js"></script>

<!-- SVG container -->
<svg id="myChart" width="400" height="200"></svg>

<script>
// Simple bar chart with D3
const data = [30, 86, 168, 281, 303, 365];

d3.select("#myChart")
  .selectAll("rect")
  .data(data)
  .enter()
  .append("rect")
  .attr("x", (d, i) => i * 60)
  .attr("y", d => 200 - d)
  .attr("width", 50)
  .attr("height", d => d)
  .attr("fill", "steelblue");
</script>
                                    

Output:

D3.js Core Concepts

🎯

Selections

Select and manipulate DOM elements

d3.select("body").selectAll("p")
📊

Data Binding

Bind data to DOM elements

.data(dataset).enter()
📏

Scales

Map data values to visual properties

d3.scaleLinear().domain().range()
🎨

SVG Graphics

Create scalable vector graphics

.append("circle").attr("r", 5)

🔹 Creating a Scatter Plot

Scatter plots show relationships between two variables:

// Sample data
const dataset = [
    [5, 20], [480, 90], [250, 50], [100, 33], [330, 95],
    [410, 12], [475, 44], [25, 67], [85, 21], [220, 88]
];

// Set dimensions and margins
const margin = {top: 20, right: 20, bottom: 30, left: 40};
const width = 400 - margin.left - margin.right;
const height = 300 - margin.top - margin.bottom;

// Create SVG
const svg = d3.select("#scatterPlot")
    .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})`);

// Create scales
const xScale = d3.scaleLinear()
    .domain([0, d3.max(dataset, d => d[0])])
    .range([0, width]);

const yScale = d3.scaleLinear()
    .domain([0, d3.max(dataset, d => d[1])])
    .range([height, 0]);

// Add circles
svg.selectAll("circle")
    .data(dataset)
    .enter()
    .append("circle")
    .attr("cx", d => xScale(d[0]))
    .attr("cy", d => yScale(d[1]))
    .attr("r", 5)
    .attr("fill", "orange");

Output:

🔹 Interactive Bar Chart

Add interactivity with mouse events and transitions:

const data = [12, 5, 6, 6, 9, 10];
const width = 420;
const barHeight = 20;

const x = d3.scaleLinear()
    .domain([0, d3.max(data)])
    .range([0, width]);

const chart = d3.select("#barChart")
    .append("svg")
    .attr("width", width)
    .attr("height", barHeight * data.length);

const bar = chart.selectAll("g")
    .data(data)
    .enter().append("g")
    .attr("transform", (d, i) => `translate(0,${i * barHeight})`);

bar.append("rect")
    .attr("width", x)
    .attr("height", barHeight - 1)
    .attr("fill", "steelblue")
    .on("mouseover", function() {
        d3.select(this).attr("fill", "orange");
    })
    .on("mouseout", function() {
        d3.select(this).attr("fill", "steelblue");
    });

bar.append("text")
    .attr("x", d => x(d) - 3)
    .attr("y", barHeight / 2)
    .attr("dy", ".35em")
    .style("fill", "white")
    .text(d => d);

Output: (Hover over the bars)

🔹 Animated Transitions

D3 makes it easy to add smooth animations:

// Create circles that grow on click
const svg = d3.select("#animationDemo")
    .append("svg")
    .attr("width", 400)
    .attr("height", 200);

const circles = svg.selectAll("circle")
    .data([1, 2, 3, 4, 5])
    .enter()
    .append("circle")
    .attr("cx", (d, i) => (i * 70) + 50)
    .attr("cy", 100)
    .attr("r", 20)
    .attr("fill", "lightblue")
    .style("cursor", "pointer");

// Add click animation
circles.on("click", function() {
    d3.select(this)
        .transition()
        .duration(500)
        .attr("r", 40)
        .attr("fill", "red")
        .transition()
        .duration(500)
        .attr("r", 20)
        .attr("fill", "lightblue");
});

Output: (Click on the circles)

🔹 D3.js Boilerplate Template

A complete starter template for D3.js projects:

<!DOCTYPE html>
<html>
<head>
    <title>D3.js Visualization</title>
    <script src="https://d3js.org/d3.v7.min.js"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
        }
        .chart-container {
            margin: 20px 0;
            border: 1px solid #ddd;
            border-radius: 5px;
            padding: 15px;
        }
        .axis {
            font-size: 12px;
        }
        .axis path,
        .axis line {
            fill: none;
            stroke: #000;
            shape-rendering: crispEdges;
        }
        .tooltip {
            position: absolute;
            padding: 10px;
            background: rgba(0, 0, 0, 0.8);
            color: white;
            border-radius: 5px;
            pointer-events: none;
            opacity: 0;
        }
    </style>
</head>
<body>
    <h1>D3.js Data Visualization Dashboard</h1>
    
    <div class="chart-container">
        <h2>Interactive Bar Chart</h2>
        <div id="barChart"></div>
    </div>
    
    <div class="chart-container">
        <h2>Scatter Plot with Axes</h2>
        <div id="scatterPlot"></div>
    </div>
    
    <div class="tooltip"></div>
    
    <script>
        // Sample data
        const barData = [
            {name: 'A', value: 30},
            {name: 'B', value: 80},
            {name: 'C', value: 45},
            {name: 'D', value: 60},
            {name: 'E', value: 20},
            {name: 'F', value: 90}
        ];
        
        const scatterData = [
            {x: 10, y: 20, category: 'Type A'},
            {x: 40, y: 90, category: 'Type B'},
            {x: 25, y: 50, category: 'Type A'},
            {x: 60, y: 70, category: 'Type C'},
            {x: 80, y: 30, category: 'Type B'}
        ];
        
        // Chart dimensions
        const margin = {top: 20, right: 20, bottom: 40, left: 40};
        const width = 600 - margin.left - margin.right;
        const height = 400 - margin.top - margin.bottom;
        
        // Create tooltip
        const tooltip = d3.select(".tooltip");
        
        // Bar Chart
        function createBarChart() {
            const svg = d3.select("#barChart")
                .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})`);
            
            const xScale = d3.scaleBand()
                .domain(barData.map(d => d.name))
                .range([0, width])
                .padding(0.1);
            
            const yScale = d3.scaleLinear()
                .domain([0, d3.max(barData, d => d.value)])
                .range([height, 0]);
            
            // Add bars
            svg.selectAll(".bar")
                .data(barData)
                .enter().append("rect")
                .attr("class", "bar")
                .attr("x", d => xScale(d.name))
                .attr("width", xScale.bandwidth())
                .attr("y", d => yScale(d.value))
                .attr("height", d => height - yScale(d.value))
                .attr("fill", "steelblue")
                .on("mouseover", function(event, d) {
                    d3.select(this).attr("fill", "orange");
                    tooltip.transition().duration(200).style("opacity", .9);
                    tooltip.html(`${d.name}: ${d.value}`)
                        .style("left", (event.pageX + 10) + "px")
                        .style("top", (event.pageY - 28) + "px");
                })
                .on("mouseout", function() {
                    d3.select(this).attr("fill", "steelblue");
                    tooltip.transition().duration(500).style("opacity", 0);
                });
            
            // Add axes
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", `translate(0,${height})`)
                .call(d3.axisBottom(xScale));
            
            svg.append("g")
                .attr("class", "axis")
                .call(d3.axisLeft(yScale));
        }
        
        // Scatter Plot
        function createScatterPlot() {
            const svg = d3.select("#scatterPlot")
                .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})`);
            
            const xScale = d3.scaleLinear()
                .domain([0, d3.max(scatterData, d => d.x)])
                .range([0, width]);
            
            const yScale = d3.scaleLinear()
                .domain([0, d3.max(scatterData, d => d.y)])
                .range([height, 0]);
            
            const colorScale = d3.scaleOrdinal()
                .domain(['Type A', 'Type B', 'Type C'])
                .range(['#ff7f0e', '#2ca02c', '#d62728']);
            
            // Add circles
            svg.selectAll(".dot")
                .data(scatterData)
                .enter().append("circle")
                .attr("class", "dot")
                .attr("r", 8)
                .attr("cx", d => xScale(d.x))
                .attr("cy", d => yScale(d.y))
                .attr("fill", d => colorScale(d.category))
                .on("mouseover", function(event, d) {
                    d3.select(this).attr("r", 12);
                    tooltip.transition().duration(200).style("opacity", .9);
                    tooltip.html(`${d.category}<br/>X: ${d.x}, Y: ${d.y}`)
                        .style("left", (event.pageX + 10) + "px")
                        .style("top", (event.pageY - 28) + "px");
                })
                .on("mouseout", function() {
                    d3.select(this).attr("r", 8);
                    tooltip.transition().duration(500).style("opacity", 0);
                });
            
            // Add axes
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", `translate(0,${height})`)
                .call(d3.axisBottom(xScale));
            
            svg.append("g")
                .attr("class", "axis")
                .call(d3.axisLeft(yScale));
        }
        
        // Initialize charts
        createBarChart();
        createScatterPlot();
    </script>
</body>
</html>

🧠 Test Your Knowledge

What does D3.js stand for?