d3-visualization
Create sophisticated, interactive data visualizations using D3.js. Use for custom charts, network visualizations, or when Recharts/charting libraries are insufficient.
When & Why to Use This Skill
The D3.js Visualization skill enables the creation of sophisticated, interactive, and highly customized data visualizations. It is designed for scenarios where standard charting libraries are insufficient, providing deep control over SVG, Canvas, and HTML to build complex network graphs, geographic maps, and fluid, choreographed transitions for professional data storytelling.
Use Cases
- Developing custom network and hierarchy visualizations using force-directed layouts to represent complex data relationships.
- Creating interactive geographic visualizations and maps with custom projections for spatial and demographic data analysis.
- Building high-performance data dashboards that require unique visual encodings and the ability to handle large datasets efficiently.
- Designing publication-quality interactive charts with fine-grained styling and smooth transitions for engaging data presentations.
- Implementing advanced user interactions such as complex panning, zooming, and brushing for deep data exploration.
| name | d3-visualization |
|---|---|
| description | Create sophisticated, interactive data visualizations using D3.js. Use for custom charts, network visualizations, or when Recharts/charting libraries are insufficient. |
D3.js Visualization Skill
This skill provides guidance for creating sophisticated, interactive data visualizations using D3.js.
When to Use D3.js
Use D3.js for:
- Custom visualizations requiring unique visual encodings or layouts
- Interactive explorations with complex pan, zoom, or brush behaviors
- Network/graph visualizations (force-directed layouts, tree diagrams, hierarchies)
- Geographic visualizations with custom projections
- Visualizations requiring smooth, choreographed transitions
- Publication-quality graphics with fine-grained styling control
Consider alternatives for:
- Standard charts (bar, line, pie) → Use Recharts (already in your stack)
- 3D visualizations → Use Three.js
- Simple dashboards → Use your existing Recharts components
Core Workflow
1. Set Up D3.js
import * as d3 from 'd3';
2. Structure the Visualization Code
function drawVisualization(data, svgElement) {
if (!data || data.length === 0) return;
const svg = d3.select(svgElement);
svg.selectAll("*").remove(); // Clear previous render
// 1. Define dimensions
const width = 800;
const height = 400;
const margin = { top: 20, right: 30, bottom: 40, left: 50 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
// 2. Create main group with margins
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
// 3. Create scales
const xScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.x)])
.range([0, innerWidth]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.y)])
.range([innerHeight, 0]); // Inverted for SVG coordinates
// 4. Create and append axes
g.append("g")
.attr("transform", `translate(0,${innerHeight})`)
.call(d3.axisBottom(xScale));
g.append("g")
.call(d3.axisLeft(yScale));
// 5. Bind data and create visual elements
g.selectAll("circle")
.data(data)
.join("circle")
.attr("cx", d => xScale(d.x))
.attr("cy", d => yScale(d.y))
.attr("r", 5)
.attr("fill", "steelblue");
}
3. Implement Responsive Sizing
function setupResponsiveChart(containerId, data) {
const container = document.getElementById(containerId);
const svg = d3.select(`#${containerId}`).append('svg');
function updateChart() {
const { width, height } = container.getBoundingClientRect();
svg.attr('width', width).attr('height', height);
drawChart(data, svg, width, height);
}
updateChart();
window.addEventListener('resize', updateChart);
return () => window.removeEventListener('resize', updateChart);
}
Common Patterns
Bar Chart
const xScale = d3.scaleBand()
.domain(data.map(d => d.category))
.range([0, innerWidth])
.padding(0.1);
g.selectAll("rect")
.data(data)
.join("rect")
.attr("x", d => xScale(d.category))
.attr("y", d => yScale(d.value))
.attr("width", xScale.bandwidth())
.attr("height", d => innerHeight - yScale(d.value))
.attr("fill", "steelblue");
Line Chart
const line = d3.line()
.x(d => xScale(d.date))
.y(d => yScale(d.value))
.curve(d3.curveMonotoneX);
g.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 2)
.attr("d", line);
Best Practices
Data Preparation
const cleanData = data.filter(d => d.value != null && !isNaN(d.value));
const sortedData = [...data].sort((a, b) => b.value - a.value);
Accessibility
svg.attr("role", "img")
.attr("aria-label", "Bar chart showing quarterly revenue");
svg.append("title").text("Quarterly Revenue 2024");
Consistent Styling
const colours = {
primary: '#4A90E2',
secondary: '#7B68EE',
background: '#F5F7FA',
text: '#333333',
gridLines: '#E0E0E0'
};
svg.selectAll("text")
.style("font-family", "Inter, sans-serif")
.style("font-size", "12px");
Performance (>1000 elements)
- Use canvas instead of SVG for many elements
- Use quadtree for collision detection
- Simplify paths with
d3.line().curve(d3.curveStep) - Implement virtual scrolling for large lists