Code
D3.js
Select & Style
Select elements and apply styles with d3.select() and d3.selectAll().
Data Binding
Bind arrays to DOM elements using the enter / join / exit pattern.
Bar Chart
Vertical bar chart with scaleBand, scaleLinear, and axis helpers.
Scales
Linear, sqrt, log, and sequential colour scales compared visually.
Line Chart
Multi-series time-series line chart with area fill.
Scatter Plot
Scatter plot with colour and size encoding per group.
Pie / Donut Chart
Donut chart using d3.pie() and d3.arc() with percent labels.
Area Chart
Stacked area chart with d3.stack() and scaleTime.
Histogram
Frequency histogram with d3.bin() and a normal-curve overlay.
Transitions
Animated attribute changes with easing functions and callbacks.
Zoom & Pan
Scroll-to-zoom and drag-to-pan via d3.zoom().
Force Graph
Draggable force-directed network graph with forceSimulation.
Treemap
Hierarchical squarified treemap with d3.hierarchy() and d3.treemap().
Chord Diagram
Relationship matrix visualised as a chord diagram with d3.chord().
Brush
Focus+context: brush a time window in the overview to filter the detail view.
Generative Art
Animated flow-field generative art with sine-harmonic noise and sequential colour scales.
Generative Art
Expert Animated flow-field using sine-harmonic noise to steer 600 particles across a dark canvas. Each particle draws a short line per frame — colour mapped to its Y position via d3.scaleSequential and stroke-width by distance from centre via d3.scalePow. DOM is pruned automatically to keep rendering smooth.
// Colour: D3 sequential scale over palette
const color = d3.scaleSequential(
d3.interpolateRgbBasis(palette)
).domain([0, height]);
// Stroke-width: power scale from centre
const strokeScale = d3.scalePow()
.exponent(0.6)
.domain([0, maxDist])
.range([0.3, 1.8]);
// Flow-field angle at (x, y, time)
const angle = (x, y, t) =>
Math.sin(x / W * 3.1 + t * 0.007) * Math.PI +
Math.cos(y / H * 2.7 + t * 0.005) * Math.PI +
Math.sin((x/W + y/H) * 4.3
+ t * 0.009) * Math.PI * 0.5;
// Animate — draw trail segments each frame
const animate = () => {
for (const p of particles) {
const a = angle(p.x, p.y, frame);
p.x += Math.cos(a) * speed;
p.y += Math.sin(a) * speed;
svg.append('line')
.attr('x1', px).attr('y1', py)
.attr('x2', p.x).attr('y2', p.y)
.attr('stroke', color(p.y))
.attr('stroke-width',
strokeScale(dist));
}
requestAnimationFrame(animate);
};Key APIs & Techniques
d3.scaleSequential(interpolator)— maps a continuous domain to a colour interpolatord3.interpolateRgbBasis(colours)— smooth spline interpolation through an array of coloursd3.scalePow().exponent()— power scale for non-linear stroke-width mapping- Flow-field — each pixel has an angle derived from overlapping sine waves; particles follow it
- Trail rendering — one
<line>per particle per frame accumulates into a painting - DOM pruning —
d3.selectAll().filter().remove()keeps the SVG node count bounded NgZone.runOutsideAngular()— avoids triggering Angular change detection on every animation frame