| name | d3-viz |
| description | Create interactive data visualizations using D3.js. Use this when creating charts, graphs, network diagrams, geographic visualizations, or custom SVG-based data visualization. |
| allowed-tools | Read, Glob, Grep, Edit, Write |
| license | MIT |
| metadata | {"author":"chrisvoncsefalvay","version":"1.0"} |
D3.js Visualization
D3.js๋ฅผ ์ฌ์ฉํ ์ธํฐ๋ํฐ๋ธ ๋ฐ์ดํฐ ์๊ฐํ ๊ฐ์ด๋์
๋๋ค.
When to Use D3.js
์ ํฉํ ๊ฒฝ์ฐ:
- ์ปค์คํ
์ฐจํธ (ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์๋)
- ์ธํฐ๋ํฐ๋ธ ํ์ (pan, zoom, brush)
- ๋คํธ์ํฌ/๊ทธ๋ํ ์๊ฐํ
- ์ง๋ฆฌ ์๊ฐํ (์ปค์คํ
projection)
- ์ ๋๋ฉ์ด์
transition
- ์ถํ ํ์ง ๊ทธ๋ํฝ
๋์ ๊ณ ๋ ค:
- 3D ์๊ฐํ โ Three.js
- ๊ฐ๋จํ ์ฐจํธ โ Chart.js, Recharts
Setup
import * as d3 from 'd3';
<script src="https://d3js.org/d3.v7.min.js"></script>
Core Workflow
function drawVisualization(data) {
if (!data || data.length === 0) return;
const svg = d3.select('#chart');
svg.selectAll("*").remove();
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;
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
const xScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.x)])
.([, innerWidth]);
yScale = d3.()
.([, d3.(data, d.)])
.([innerHeight, ]);
g.()
.(, )
.(d3.(xScale));
g.()
.(d3.(yScale));
g.()
.(data)
.()
.(, (d.))
.(, (d.))
.(, )
.(, );
}
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);
Pie Chart
const pie = d3.pie().value(d => d.value);
const arc = d3.arc()
.innerRadius(0)
.outerRadius(Math.min(width, height) / 2 - 20);
g.selectAll("path")
.data(pie(data))
.join("path")
.attr("d", arc)
.attr("fill", (d, i) => d3.schemeCategory10[i]);
Interactivity
Tooltips
const tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("visibility", "hidden");
circles
.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);
Transitions
circles.transition()
.duration(750)
.attr("r", 10);
circles.transition()
.delay((d, i) => i * 50)
.duration(500)
.attr("cy", d => yScale(d.value));
Scales Reference
| Scale Type | Use Case |
|---|
scaleLinear | ์ฐ์ ์์น |
scaleLog | ์ง์ ๋ฐ์ดํฐ |
scaleTime | ์๊ฐ/๋ ์ง |
scaleBand | Bar chart ์นดํ
๊ณ ๋ฆฌ |
scaleOrdinal | ์์ ๋งคํ |
scaleSequential | ์ฐ์ ์์ |
Color Schemes
d3.schemeCategory10
d3.schemeTableau10
d3.interpolateBlues
d3.interpolateYlOrRd
d3.interpolateRdBu
Best Practices
- Data Validation: null/NaN ์ฒดํฌ
- Responsive: ResizeObserver ์ฌ์ฉ
- Performance: 1000+ ์์ ์ Canvas ๊ณ ๋ ค
- Accessibility: ARIA labels ์ถ๊ฐ
- Clean Up: ์ด์ ๋ ๋๋ง ์ ๊ฑฐ