SVG Elements & Shapes
Quick reference for creating and manipulating SVG elements with D3.js.
Basic SVG Setup
Creating SVG Container
const svg = d3
.select('body')
.append('svg')
.attr('width', 500)
.attr('height', 300);
// With viewBox for responsive design
const svg2 = d3
.select('#chart')
.append('svg')
.attr('viewBox', '0 0 500 300')
.attr('preserveAspectRatio', 'xMidYMid meet');
Creating Groups for Organization
// Main group with transform
const g = svg.append('g').attr('transform', 'translate(50,50)');
// Multiple groups for different layers
const chartArea = svg
.append('g')
.attr('class', 'chart-area')
.attr('transform', `translate(${margin.left},${margin.top})`);
const axisGroup = svg.append('g').attr('class', 'axes');
const dataGroup = svg.append('g').attr('class', 'data');
Basic Shapes
Rectangle
svg
.append('rect')
.attr('x', 10)
.attr('y', 10)
.attr('width', 100)
.attr('height', 50)
.attr('fill', 'blue')
.attr('stroke', 'black')
.attr('stroke-width', 2)
.attr('rx', 5) // Rounded corners
.attr('ry', 5);
Circle
svg
.append('circle')
.attr('cx', 100) // Center x
.attr('cy', 100) // Center y
.attr('r', 25) // Radius
.attr('fill', 'red')
.attr('stroke', 'darkred')
.attr('stroke-width', 2);
Ellipse
svg
.append('ellipse')
.attr('cx', 100)
.attr('cy', 100)
.attr('rx', 50) // Horizontal radius
.attr('ry', 25) // Vertical radius
.attr('fill', 'green');
Line
svg
.append('line')
.attr('x1', 0)
.attr('y1', 0)
.attr('x2', 100)
.attr('y2', 100)
.attr('stroke', 'black')
.attr('stroke-width', 2)
.attr('stroke-dasharray', '5,5'); // Dashed line
Polyline
svg
.append('polyline')
.attr('points', '10,10 50,50 100,30 150,80')
.attr('fill', 'none')
.attr('stroke', 'blue')
.attr('stroke-width', 2);
Polygon
svg
.append('polygon')
.attr('points', '100,10 40,198 190,78 10,78 160,198')
.attr('fill', 'orange')
.attr('stroke', 'red')
.attr('stroke-width', 3);
Path Element
Basic Path
svg
.append('path')
.attr('d', 'M 10 10 L 50 50 L 100 10 Z') // Z closes the path
.attr('fill', 'green')
.attr('stroke', 'darkgreen')
.attr('stroke-width', 2);
Path Commands
// Move to, Line to, Curve, Arc examples
const pathData = [
'M 50 50', // Move to (50,50)
'L 100 50', // Line to (100,50)
'L 100 100', // Line to (100,100)
'Q 125 125 150 100', // Quadratic curve
'A 25 25 0 0 1 200 100', // Arc
'Z', // Close path
].join(' ');
svg
.append('path')
.attr('d', pathData)
.attr('fill', 'lightblue')
.attr('stroke', 'blue');
Using D3 Path Generators
// Line generator
const line = d3
.line()
.x(d => d.x)
.y(d => d.y)
.curve(d3.curveLinear);
const data = [
{ x: 10, y: 10 },
{ x: 50, y: 50 },
{ x: 100, y: 30 },
];
svg
.append('path')
.datum(data)
.attr('d', line)
.attr('fill', 'none')
.attr('stroke', 'steelblue')
.attr('stroke-width', 2);
Text Elements
Basic Text
svg
.append('text')
.attr('x', 50)
.attr('y', 50)
.text('Hello, D3!')
.attr('font-family', 'Arial')
.attr('font-size', '14px')
.attr('fill', 'black')
.attr('text-anchor', 'middle'); // start, middle, end
Text with Data
const data = [10, 20, 30, 40];
svg
.selectAll('text')
.data(data)
.join('text')
.attr('x', (d, i) => i * 50 + 25)
.attr('y', 50)
.text(d => d)
.attr('text-anchor', 'middle')
.attr('font-size', '12px');
Multi-line Text with tspan
const textGroup = svg.append('text').attr('x', 50).attr('y', 50);
textGroup.append('tspan').text('First line').attr('x', 50).attr('dy', 0);
textGroup.append('tspan').text('Second line').attr('x', 50).attr('dy', '1.2em');
Text on Path
// Define a path
svg
.append('defs')
.append('path')
.attr('id', 'textpath')
.attr('d', 'M 50 100 Q 100 50 150 100');
// Add text following the path
svg
.append('text')
.append('textPath')
.attr('href', '#textpath')
.text('Text following a curve');
Styling and Attributes
Common Fill Patterns
// Solid colors
.attr("fill", "red")
.attr("fill", "#ff0000")
.attr("fill", "rgb(255,0,0)")
// Gradients (defined in defs)
.attr("fill", "url(#myGradient)")
// Patterns
.attr("fill", "url(#myPattern)")
// Transparent
.attr("fill", "none")
.attr("fill-opacity", 0.5)
Stroke Properties
.attr("stroke", "black")
.attr("stroke-width", 2)
.attr("stroke-opacity", 0.8)
.attr("stroke-dasharray", "5,5") // Dashed
.attr("stroke-dasharray", "10,5,5,5") // Custom dash pattern
.attr("stroke-linecap", "round") // butt, round, square
.attr("stroke-linejoin", "round") // miter, round, bevel
Transforms
// Translate
.attr("transform", "translate(50,100)")
// Scale
.attr("transform", "scale(1.5)")
// Rotate (degrees around origin)
.attr("transform", "rotate(45)")
// Rotate around point
.attr("transform", "rotate(45,100,100)")
// Combine transforms
.attr("transform", "translate(50,100) scale(1.5) rotate(45)")
Gradients and Patterns
Linear Gradient
// Define gradient in defs
const defs = svg.append('defs');
const gradient = defs
.append('linearGradient')
.attr('id', 'myGradient')
.attr('x1', '0%')
.attr('y1', '0%')
.attr('x2', '100%')
.attr('y2', '0%');
gradient.append('stop').attr('offset', '0%').attr('stop-color', 'red');
gradient.append('stop').attr('offset', '100%').attr('stop-color', 'blue');
// Use gradient
svg.append('rect').attr('fill', 'url(#myGradient)');
Radial Gradient
const radialGradient = defs
.append('radialGradient')
.attr('id', 'radialGradient')
.attr('cx', '50%')
.attr('cy', '50%')
.attr('r', '50%');
radialGradient.append('stop').attr('offset', '0%').attr('stop-color', 'white');
radialGradient
.append('stop')
.attr('offset', '100%')
.attr('stop-color', 'black');
Pattern
const pattern = defs
.append('pattern')
.attr('id', 'dots')
.attr('patternUnits', 'userSpaceOnUse')
.attr('width', 10)
.attr('height', 10);
pattern
.append('circle')
.attr('cx', 5)
.attr('cy', 5)
.attr('r', 2)
.attr('fill', 'red');
Performance Tips
Efficient Shape Creation
// Use join for data-driven shapes
svg
.selectAll('circle')
.data(data)
.join('circle')
.attr('cx', d => xScale(d.x))
.attr('cy', d => yScale(d.y))
.attr('r', 5);
// Group similar elements
const circles = svg
.append('g')
.attr('class', 'circles')
.selectAll('circle')
.data(data)
.join('circle');
CSS vs Attributes
// Use CSS classes for styling when possible
.style("fill", "red") // Inline style
.classed("highlighted", true) // CSS class (preferred)