Files
gh-lyndonkl-claude/skills/d3-visualization/SKILL.md
2025-11-30 08:38:26 +08:00

333 lines
15 KiB
Markdown

---
name: d3-visualization
description: Use when creating custom, interactive data visualizations with D3.js—building bar/line/scatter charts from scratch, creating network diagrams or geographic maps, binding changing data to visual elements, adding zoom/pan/brush interactions, animating chart transitions, or when chart libraries (Highcharts, Chart.js) don't support your specific visualization design and you need low-level control over data-driven DOM manipulation, scales, shapes, and layouts.
---
# D3.js Data Visualization
## Table of Contents
- [Read This First](#read-this-first)
- [Workflows](#workflows)
- [Create Basic Chart Workflow](#create-basic-chart-workflow)
- [Update Visualization with New Data](#update-visualization-with-new-data)
- [Create Advanced Layout Workflow](#create-advanced-layout-workflow)
- [Path Selection Menu](#path-selection-menu)
- [Quick Reference](#quick-reference)
---
## Read This First
### What This Skill Does
This skill helps you create custom, interactive data visualizations using D3.js (Data-Driven Documents). D3 provides low-level building blocks for data-driven DOM manipulation, visual encoding, layout algorithms, and interactions—enabling bespoke visualizations that chart libraries can't provide.
### When to Use D3
**Use D3 when:**
- Chart libraries don't support your specific design
- You need full customization control
- Creating network graphs, hierarchies, or geographic maps
- Building interactive dashboards with linked views
- Animating data changes smoothly
- Working with complex or unconventional data structures
**Don't use D3 when:**
- Simple bar/line charts suffice (use Chart.js, Highcharts—easier)
- You need 3D visualizations (use Three.js, WebGL)
- Massive datasets >10K points without aggregation (performance limitations)
- You're unfamiliar with JavaScript/SVG/CSS (prerequisites required)
### Core Concepts
**Data Joins**: Bind arrays to DOM elements, creating one-to-one correspondence
**Scales**: Transform data values → visual values (pixels, colors, sizes)
**Shapes**: Generate SVG paths for lines, areas, arcs from data
**Layouts**: Calculate positions for complex visualizations (networks, trees, maps)
**Transitions**: Animate smooth changes between states
**Interactions**: Add zoom, pan, drag, brush selection behaviors
### Skill Structure
- **[Getting Started](resources/getting-started.md)**: Setup, prerequisites, first visualization
- **[Selections & Data Joins](resources/selections-datajoins.md)**: DOM manipulation, data binding
- **[Scales & Axes](resources/scales-axes.md)**: Data transformation, axis generation
- **[Shapes & Layouts](resources/shapes-layouts.md)**: Path generators, basic layouts
- **[Advanced Layouts](resources/advanced-layouts.md)**: Force simulation, hierarchies, geographic maps
- **[Transitions & Interactions](resources/transitions-interactions.md)**: Animations, zoom/pan/drag/brush
- **[Workflows](resources/workflows.md)**: Step-by-step guides for common chart types
- **[Common Patterns](resources/common-patterns.md)**: Reusable code templates
---
## Workflows
Choose a workflow based on your current task:
### Create Basic Chart Workflow
**Use when:** Building bar, line, or scatter charts from scratch
**Time:** 1-2 hours
**Copy this checklist and track your progress:**
```
Basic Chart Progress:
- [ ] Step 1: Set up SVG container with margins
- [ ] Step 2: Load and parse data
- [ ] Step 3: Create scales (x, y)
- [ ] Step 4: Generate axes
- [ ] Step 5: Bind data and create visual elements
- [ ] Step 6: Style and add interactivity
```
**Step 1: Set up SVG container with margins**
Create SVG element with proper dimensions. Define margins for axes: `{top: 20, right: 20, bottom: 30, left: 40}`. Calculate inner width/height: `width - margin.left - margin.right`. See [Getting Started](resources/getting-started.md#setup-svg-container).
**Step 2: Load and parse data**
Use `d3.csv('data.csv')` for external files or define data array directly. Parse dates with `d3.timeParse('%Y-%m-%d')` for time series. Convert strings to numbers for CSV data using conversion function. See [Getting Started](resources/getting-started.md#loading-data).
**Step 3: Create scales**
Choose scale types based on data: `scaleBand` (categorical), `scaleTime` (temporal), `scaleLinear` (quantitative). Set domains from data using `d3.extent()`, `d3.max()`, or manual ranges. Set ranges from SVG dimensions. See [Scales & Axes](resources/scales-axes.md#scale-types).
**Step 4: Generate axes**
Create axis generators: `d3.axisBottom(xScale)`, `d3.axisLeft(yScale)`. Append g elements positioned with transforms. Call axis generators: `.call(axis)`. Customize ticks with `.ticks()`, `.tickFormat()`. See [Scales & Axes](resources/scales-axes.md#creating-axes).
**Step 5: Bind data and create visual elements**
Use data join pattern: `svg.selectAll(type).data(array).join(type)`. Set attributes using scales and accessor functions: `.attr('x', d => xScale(d.category))`. For line charts, use `d3.line()` generator. For scatter plots, create circles with `cx`, `cy`, `r` attributes. See [Selections & Data Joins](resources/selections-datajoins.md#data-join-pattern) and [Shapes & Layouts](resources/shapes-layouts.md).
**Step 6: Style and add interactivity**
Apply colors: `.attr('fill', ...)`, `.attr('stroke', ...)`. Add hover effects: `.on('mouseover', ...)` with tooltip. Add click handlers for drill-down. Apply transitions for initial animation (optional). See [Transitions & Interactions](resources/transitions-interactions.md#tooltips) and [Common Patterns](resources/common-patterns.md#tooltip-pattern).
---
### Update Visualization with New Data
**Use when:** Refreshing charts with new data (real-time, filters, user interactions)
**Time:** 30 minutes - 1 hour
**Copy this checklist:**
```
Update Progress:
- [ ] Step 1: Encapsulate visualization in update function
- [ ] Step 2: Update scale domains if needed
- [ ] Step 3: Re-bind data with key function
- [ ] Step 4: Add transitions to join
- [ ] Step 5: Update attributes with new values
- [ ] Step 6: Trigger update on data change
```
**Step 1: Encapsulate visualization in update function**
Wrap steps 3-5 from basic chart workflow in `function update(newData) { ... }`. This makes visualization reusable for any dataset. See [Workflows](resources/workflows.md#update-pattern).
**Step 2: Update scale domains**
Recalculate domains when data range changes: `yScale.domain([0, d3.max(newData, d => d.value)])`. Update axes with transition: `svg.select('.y-axis').transition().duration(500).call(yAxis)`. See [Selections & Data Joins](resources/selections-datajoins.md#updating-scales).
**Step 3: Re-bind data with key function**
Use key function for object constancy: `.data(newData, d => d.id)`. Ensures elements track data items, not array positions. Critical for correct transitions. See [Selections & Data Joins](resources/selections-datajoins.md#key-functions).
**Step 4: Add transitions to join**
Insert `.transition().duration(500)` before attribute updates. Specify easing with `.ease(d3.easeCubicOut)`. For custom enter/exit effects, use enter/exit functions in `.join()`. See [Transitions & Interactions](resources/transitions-interactions.md#basic-transitions).
**Step 5: Update attributes with new values**
Set positions/sizes using updated scales: `.attr('y', d => yScale(d.value))`, `.attr('height', d => height - yScale(d.value))`. Transitions animate from old to new values. See [Common Patterns](resources/common-patterns.md#bar-chart-template).
**Step 6: Trigger update on data change**
Call `update(newData)` when data changes: button clicks, timers (`setInterval`), WebSocket messages, API responses. For real-time, use sliding window to limit data points. See [Workflows](resources/workflows.md#real-time-updates).
---
### Create Advanced Layout Workflow
**Use when:** Building network graphs, hierarchies, or geographic maps
**Time:** 2-4 hours
**Copy this checklist:**
```
Advanced Layout Progress:
- [ ] Step 1: Choose appropriate layout type
- [ ] Step 2: Prepare and structure data
- [ ] Step 3: Create and configure layout
- [ ] Step 4: Apply layout to data
- [ ] Step 5: Bind computed properties to elements
- [ ] Step 6: Add interactions (drag, zoom)
```
**Step 1: Choose appropriate layout type**
**Force Simulation**: Network diagrams, organic clustering. **Hierarchies**: Tree, cluster (node-link), treemap, pack, partition (space-filling). **Geographic**: Maps with projections. **Chord**: Flow diagrams. See [Advanced Layouts](resources/advanced-layouts.md#choosing-layout) for decision guidance.
**Step 2: Prepare and structure data**
**Force**: `nodes = [{id, group}]`, `links = [{source, target}]`. **Hierarchy**: Nested objects with children arrays, convert with `d3.hierarchy(data)`. **Geographic**: GeoJSON features. See [Advanced Layouts](resources/advanced-layouts.md#data-structures).
**Step 3: Create and configure layout**
**Force**: `d3.forceSimulation(nodes).force('link', d3.forceLink(links)).force('charge', d3.forceManyBody())`. **Hierarchy**: `d3.treemap().size([width, height])`. **Geographic**: `d3.geoMercator().fitExtent([[0,0], [width,height]], geojson)`. See [Advanced Layouts](resources/advanced-layouts.md) for each layout type.
**Step 4: Apply layout to data**
**Force**: Simulation runs automatically, updates node positions each tick. **Hierarchy**: Call layout on root: `treemap(root)`. **Geographic**: No application needed, projection used in path generator. See [Advanced Layouts](resources/advanced-layouts.md#applying-layouts).
**Step 5: Bind computed properties to elements**
**Force**: Update `cx`, `cy` in tick handler: `node.attr('cx', d => d.x)`. **Hierarchy**: Use `d.x0`, `d.x1`, `d.y0`, `d.y1` for rectangles. **Geographic**: Use `path(feature)` for `d` attribute. See [Workflows](resources/workflows.md) for layout-specific examples.
**Step 6: Add interactions**
**Drag** for force networks: `node.call(d3.drag().on('drag', dragHandler))`. **Zoom** for maps/large networks: `svg.call(d3.zoom().on('zoom', zoomHandler))`. **Click** for hierarchy drill-down. See [Transitions & Interactions](resources/transitions-interactions.md).
---
## Path Selection Menu
**What would you like to do?**
1. **[I'm new to D3](resources/getting-started.md)** - Setup environment, understand prerequisites, create first visualization
2. **[Build a basic chart](resources/workflows.md#basic-charts)** - Bar, line, or scatter plot step-by-step
3. **[Transform data with scales](resources/scales-axes.md)** - Map data values to visual properties (positions, colors, sizes)
4. **[Bind data to elements](resources/selections-datajoins.md)** - Connect arrays to DOM elements, handle dynamic updates
5. **[Create network/hierarchy/map](resources/advanced-layouts.md)** - Force-directed graphs, treemaps, geographic visualizations
6. **[Add animations](resources/transitions-interactions.md#transitions)** - Smooth transitions between chart states
7. **[Add interactivity](resources/transitions-interactions.md#interactions)** - Zoom, pan, drag, brush selection, tooltips
8. **[Update chart with new data](resources/workflows.md#update-pattern)** - Handle real-time data, filters, user interactions
9. **[Get code templates](resources/common-patterns.md)** - Copy-paste-modify templates for common patterns
10. **[Understand D3 concepts](resources/getting-started.md#core-concepts)** - Deep dive into data joins, scales, generators, layouts
---
## Quick Reference
### Data Join Pattern (Core D3 Workflow)
```javascript
// 1. Select container
const svg = d3.select('svg');
// 2. Bind data
svg.selectAll('circle')
.data(dataArray)
.join('circle') // Create/update/remove elements automatically
.attr('cx', d => d.x) // Use accessor functions (d = datum, i = index)
.attr('cy', d => d.y)
.attr('r', 5);
```
### Scale Creation (Data → Visual Transformation)
```javascript
// For quantitative data
const xScale = d3.scaleLinear()
.domain([0, 100]) // Data range
.range([0, 500]); // Pixel range
// For categorical data
const xScale = d3.scaleBand()
.domain(['A', 'B', 'C'])
.range([0, 500])
.padding(0.1);
// For temporal data
const xScale = d3.scaleTime()
.domain([new Date(2020, 0, 1), new Date(2020, 11, 31)])
.range([0, 500]);
```
### Shape Generators (SVG Path Creation)
```javascript
// Line chart
const line = d3.line()
.x(d => xScale(d.date))
.y(d => yScale(d.value));
svg.append('path')
.datum(data) // Use .datum() for single data item
.attr('d', line) // Line generator creates path data
.attr('fill', 'none')
.attr('stroke', 'steelblue');
```
### Transitions (Animation)
```javascript
// Add transition before attribute updates
svg.selectAll('rect')
.data(newData)
.join('rect')
.transition() // Everything after this is animated
.duration(500) // Milliseconds
.attr('height', d => yScale(d.value));
```
### Common Scale Types
| Data Type | Task | Scale |
|-----------|------|-------|
| Quantitative (linear) | Position, size | `scaleLinear()` |
| Quantitative (exponential) | Compress range | `scaleLog()`, `scalePow()` |
| Quantitative → Circle area | Size circles | `scaleSqrt()` |
| Categorical | Bars, groups | `scaleBand()`, `scalePoint()` |
| Categorical → Colors | Color encoding | `scaleOrdinal()` |
| Temporal | Time series | `scaleTime()` |
| Quantitative → Colors | Heatmaps | `scaleSequential()` |
### D3 Module Imports (ES6)
```javascript
// Specific functions
import { select, selectAll } from 'd3-selection';
import { scaleLinear, scaleBand } from 'd3-scale';
import { line, area } from 'd3-shape';
// Entire D3 namespace
import * as d3 from 'd3';
```
### Key Resources by Task
- **Setup & First Chart**: [Getting Started](resources/getting-started.md)
- **Data Binding**: [Selections & Data Joins](resources/selections-datajoins.md)
- **Scales & Axes**: [Scales & Axes](resources/scales-axes.md)
- **Chart Types**: [Workflows](resources/workflows.md) + [Common Patterns](resources/common-patterns.md)
- **Networks & Trees**: [Advanced Layouts](resources/advanced-layouts.md#force-simulation) + [Advanced Layouts](resources/advanced-layouts.md#hierarchies)
- **Maps**: [Advanced Layouts](resources/advanced-layouts.md#geographic-maps)
- **Animation**: [Transitions & Interactions](resources/transitions-interactions.md#transitions)
- **Interactivity**: [Transitions & Interactions](resources/transitions-interactions.md#interactions)
---
## Next Steps
1. **New to D3?** Start with [Getting Started](resources/getting-started.md)
2. **Know basics?** Jump to [Workflows](resources/workflows.md) for specific chart types
3. **Need reference?** Use [Common Patterns](resources/common-patterns.md) for templates
4. **Build custom viz?** Explore [Advanced Layouts](resources/advanced-layouts.md)