d3js-visualization
Skill1 starsChanged 9 months agoMITView on GitHub
Create interactive data visualizations using D3.js. Use when building charts, graphs, maps, or custom visualizations for dashboards and data analysis.
Files
D3.js Data Visualization
When to Use This Skill
- Creating interactive charts and graphs
- Building custom data visualizations
- Implementing dashboards
- Visualizing hierarchical or network data
- Creating animated transitions
- Building geographic visualizations
Core Concepts
Selection & Data Binding
import * as d3 from 'd3';
// Select elements
const svg = d3.select('#chart');
const circles = svg.selectAll('circle');
// Data binding (the enter-update-exit pattern)
const data = [10, 20, 30, 40, 50];
const circles = svg.selectAll('circle')
.data(data)
.join(
enter => enter.append('circle')
.attr('cy', 50)
.attr('r', 0)
.call(enter => enter.transition()
.attr('r', d => d)),
update => update
.call(update => update.transition()
.attr('r', d => d)),
exit => exit
.call(exit => exit.transition()
.attr('r', 0)
.remove())
)
.attr('cx', (d, i) => i * 60 + 30)
.attr('fill', 'steelblue');Common Charts
Bar Chart
function barChart(container, data, { width = 600, height = 400, margin = { top: 20, right: 20, bottom: 30, left: 40 } } = {}) {
const svg = d3.select(container)
.append('svg')
.attr('viewBox', [0, 0, width, height]);
const x = d3.scaleBand()
.domain(data.map(d => d.name))
.range([margin.left, width - margin.right])
.padding(0.1);
const y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.nice()
.range([height - margin.bottom, margin.top]);
// Bars
svg.selectAll('rect')
.data(data)
.join('rect')
.attr('x', d => x(d.name))
.attr('y', d => y(d.value))
.attr('width', x.bandwidth())
.attr('height', d => y(0) - y(d.value))
.attr('fill', 'steelblue');
// X axis
svg.append('g')
.attr('transform', `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x));
// Y axis
svg.append('g')
.attr('transform', `translate(${margin.left},0)`)
.call(d3.axisLeft(y));
return svg.node();
}Line Chart
function lineChart(container, data, { width = 600, height = 400, margin = { top: 20, right: 20, bottom: 30, left: 40 } } = {}) {
const svg = d3.select(container)
.append('svg')
.attr('viewBox', [0, 0, width, height]);
const x = d3.scaleTime()
.domain(d3.extent(data, d => d.date))
.range([margin.left, width - margin.right]);
const y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.nice()
.range([height - margin.bottom, margin.top]);
const line = d3.line()
.x(d => x(d.date))
.y(d => y(d.value))
.curve(d3.curveMonotoneX);
// Line path
svg.append('path')
.datum(data)
.attr('fill', 'none')
.attr('stroke', 'steelblue')
.attr('stroke-width', 2)
.attr('d', line);
// Dots
svg.selectAll('circle')
.data(data)
.join('circle')
.attr('cx', d => x(d.date))
.attr('cy', d => y(d.value))
.attr('r', 4)
.attr('fill', 'steelblue');
// Axes
svg.append('g')
.attr('transform', `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x));
svg.append('g')
.attr('transform', `translate(${margin.left},0)`)
.call(d3.axisLeft(y));
return svg.node();
}Pie/Donut Chart
function pieChart(container, data, { width = 400, height = 400, innerRadius = 0 } = {}) {
const radius = Math.min(width, height) / 2;
const svg = d3.select(container)
.append('svg')
.attr('viewBox', [-width / 2, -height / 2, width, height]);
const color = d3.scaleOrdinal()
.domain(data.map(d => d.name))
.range(d3.schemeCategory10);
const pie = d3.pie()
.value(d => d.value)
.sort(null);
const arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(radius - 10);
const labelArc = d3.arc()
.innerRadius(radius * 0.6)
.outerRadius(radius * 0.6);
// Slices
svg.selectAll('path')
.data(pie(data))
.join('path')
.attr('d', arc)
.attr('fill', d => color(d.data.name))
.attr('stroke', 'white')
.attr('stroke-width', 2);
// Labels
svg.selectAll('text')
.data(pie(data))
.join('text')
.attr('transform', d => `translate(${labelArc.centroid(d)})`)
.attr('text-anchor', 'middle')
.text(d => d.data.name);
return svg.node();
}Scatter Plot
function scatterPlot(container, data, { width = 600, height = 400, margin = { top: 20, right: 20, bottom: 30, left: 40 } } = {}) {
const svg = d3.select(container)
.append('svg')
.attr('viewBox', [0, 0, width, height]);
const x = d3.scaleLinear()
.domain(d3.extent(data, d => d.x))
.nice()
.range([margin.left, width - margin.right]);
const y = d3.scaleLinear()
.domain(d3.extent(data, d => d.y))
.nice()
.range([height - margin.bottom, margin.top]);
const color = d3.scaleOrdinal(d3.schemeCategory10);
// Points
svg.selectAll('circle')
.data(data)
.join('circle')
.attr('cx', d => x(d.x))
.attr('cy', d => y(d.y))
.attr('r', 5)
.attr('fill', d => color(d.category))
.attr('opacity', 0.7);
// Axes
svg.append('g')
.attr('transform', `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x));
svg.append('g')
.attr('transform', `translate(${margin.left},0)`)
.call(d3.axisLeft(y));
return svg.node();
}Interactivity
Tooltips
const tooltip = d3.select('body')
.append('div')
.attr('class', 'tooltip')
.style('position', 'absolute')
.style('visibility', 'hidden')
.style('background', 'white')
.style('padding', '8px')
.style('border-radius', '4px')
.style('box-shadow', '0 2px 4px rgba(0,0,0,0.2)');
svg.selectAll('circle')
.on('mouseover', (event, d) => {
tooltip
.style('visibility', 'visible')
.html(`Value: ${d.value}`);
})
.on('mousemove', (event) => {
tooltip
.style('top', (event.pageY - 10) + 'px')
.style('left', (event.pageX + 10) + 'px');
})
.on('mouseout', () => {
tooltip.style('visibility', 'hidden');
});Zoom & Pan
const zoom = d3.zoom()
.scaleExtent([0.5, 10])
.on('zoom', (event) => {
g.attr('transform', event.transform);
});
svg.call(zoom);
// Reset zoom
d3.select('#reset').on('click', () => {
svg.transition()
.duration(750)
.call(zoom.transform, d3.zoomIdentity);
});Brush Selection
const brush = d3.brush()
.extent([[0, 0], [width, height]])
.on('end', (event) => {
if (!event.selection) return;
const [[x0, y0], [x1, y1]] = event.selection;
const selected = data.filter(d =>
x(d.x) >= x0 && x(d.x) <= x1 &&
y(d.y) >= y0 && y(d.y) <= y1
);
console.log('Selected:', selected);
});
svg.append('g')
.call(brush);Transitions & Animation
// Animated entry
svg.selectAll('rect')
.data(data)
.join('rect')
.attr('x', d => x(d.name))
.attr('y', height - margin.bottom)
.attr('width', x.bandwidth())
.attr('height', 0)
.transition()
.duration(1000)
.delay((d, i) => i * 100)
.ease(d3.easeElastic)
.attr('y', d => y(d.value))
.attr('height', d => y(0) - y(d.value));Responsive Design
function responsiveChart(container, data) {
const container = d3.select(container);
let svg;
function render() {
const { width } = container.node().getBoundingClientRect();
const height = width * 0.6;
container.selectAll('svg').remove();
svg = container.append('svg')
.attr('width', width)
.attr('height', height);
// Draw chart with current dimensions
drawChart(svg, data, width, height);
}
render();
// Debounced resize handler
let resizeTimer;
window.addEventListener('resize', () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(render, 100);
});
}Scale Reference
| Scale | Use Case |
scaleLinear | Continuous numeric data |
scaleTime | Date/time data |
scaleBand | Categorical (bar charts) |
scaleOrdinal | Categorical colors |
scaleLog | Exponential data |
scaleSqrt | Area-based encoding |
Best Practices
- Use viewBox for responsive SVGs
- Implement proper enter/update/exit patterns
- Add ARIA labels for accessibility
- Use transitions for state changes
- Debounce resize handlers
- Test with different data sizes
- Provide fallback for no-JS environments
Other versions3 projects use a version of this.
Word for word · 0
None found.
Edited · 2
- Bbeierle12/Skill-MCP-Claude★ 926% same
- LucasCooperBey/claude-skills★ 113% same
Wrote their own version · 1
- AutumnsGrove/ClaudeSkills★ 30same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository125 other files it gives its agents.
- skills/vercel-composition-patterns/AGENTS.mdAGENTS.md
- skills/vercel-react-best-practices/AGENTS.mdAGENTS.md
- skills/vercel-react-native-skills/AGENTS.mdAGENTS.md
- address-sanitizerSkill
- aflppSkill
- algorand-vulnerability-scannerSkill
- algorithmic-artSkill
- ask-questions-if-underspecifiedSkill
- atherisSkill
- audit-context-buildingSkill
- audit-prep-assistantSkill
- autonomous-skillSkill
- aws-skillsSkill
- better-authSkill
- brainstormingSkill
- brand-guidelinesSkill
- burpsuite-project-parserSkill
- cairo-vulnerability-scannerSkill
- canvas-designSkill
- cargo-fuzzSkill
- changelog-generatorSkill
- claude-in-chrome-troubleshootingSkill
- cloudflare-skillsSkill
- code-maturity-assessorSkill
- codeqlSkill
- codex-skillSkill
- constant-time-analysisSkill
- constant-time-testingSkill
- cosmos-vulnerability-scannerSkill
- coverage-analysisSkill
- db-resetSkill
- deep-researchSkill
- deploySkill
- dev-startSkill
- differential-reviewSkill
- dispatching-parallel-agentsSkill
- doc-coauthoringSkill
- doc-generateSkill
- documentationSkill
- docxSkill
- dwarf-expertSkill
- entry-point-analyzerSkill
- env-checkSkill
- executing-plansSkill
- expo-skillsSkill
- finishing-a-development-branchSkill
- firebase-apk-scannerSkill
- fix-reviewSkill
- frontend-designSkill
- fuzzing-dictionarySkill
- fuzzing-obstaclesSkill
- git-automationSkill
- google-design-mdSkill
- guidelines-advisorSkill
- harness-writingSkill
- health-checkSkill
- huggingface-skillsSkill
- insecure-defaultsSkill
- internal-commsSkill
- interpreting-culture-indexSkill
- The first 60 shown.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

