D3.js Brush — Interactive Selection and Filtering
In this tutorial, you will learn about D3.js Brush. We cover key concepts, practical examples, and best practices to help you master this topic.
D3.js brush creates interactive rectangular selection regions on SVG elements, enabling users to select and filter data ranges for coordinated visualizations.
What You'll Learn
By the end of this guide, you will create brush selections on X, Y, and XY axes, handle brush events to filter data, clear and programmatically set brushes, coordinate multiple charts through brushing, and build an interactive dashboard.
Basic XY Brush
var brush = d3.brush()
.extent([[0, 0], [width, height]])
.on('brush', function(event) {
var selection = event.selection;
if (selection) {
var [[x0, y0], [x1, y1]] = selection;
console.log('Brushed area:', x0, y0, x1, y1);
}
})
.on('end', function(event) {
if (!event.selection) {
console.log('Brush cleared');
}
});
svg.append('g').call(brush);
X-Only Brush
var brush = d3.brushX()
.extent([[0, 0], [width, height]])
.on('end', function(event) {
if (event.selection) {
var [x0, x1] = event.selection;
var selectedData = data.filter(function(d) {
return xScale(d.date) >= x0 && xScale(d.date) <= x1;
});
updateDetailChart(selectedData);
}
});
svg.append('g').call(brush);
Coordinated Brushing
var brush = d3.brushX()
.extent([[0, 0], [width, height]])
.on('brush', function(event) {
if (event.selection) {
var [x0, x1] = event.selection;
var domain = [xScale.invert(x0), xScale.invert(x1)];
detailXScale.domain(domain);
renderDetailChart();
}
});
Clearing the Brush
d3.select('#clear-brush').on('click', function() {
svg.select('.brush').call(brush.move, null);
});
Common Mistakes
1. Brush Not Visible
Brush extent must match the chart area dimensions. If extent is wrong, the brush rectangle appears off-screen.
2. Forgetting Brush Handle
Brush handles show on the edges. Without them, users cannot resize the selection. Handles are added automatically.
3. Not Handling Null Selection
When the brush is cleared (clicking outside), event.selection is null. Always check before processing.
4. Brush on Top of Data
The brush overlay captures mouse events. Render data elements after the brush group so they remain interactive.
5. Performance With Large Data
Filtering thousands of data points on every brush event can be slow. Debounce the brush handler.
Practice Questions
Q1: What is the difference between d3.brush, d3.brushX, and d3.brushY? A: d3.brush creates a 2D rectangle. brushX and brushY constrain selection to one axis.
Q2: What does event.selection contain? A: An array of coordinates: [[x0, y0], [x1, y1]] for 2D brush, [x0, x1] for 1D.
Q3: How do you filter data based on brush selection? A: Invert the pixel coordinates back to data values using the scale's invert method.
Q4: How do you programmatically set brush selection?
A: Use selection.call(brush.move, [[x0, y0], [x1, y1]]).
Q5: What is the difference between brush and brush event? A: The brush is the behavior. The brush event fires during interaction with the selection.
Challenge: Build a time series chart with brush selection. Below it, a detail chart shows the brushed region at full width. The detail chart updates as the brush moves.
FAQ
Try It Yourself
Build a scatter plot with XY brush that filters points and shows selected count.
<!DOCTYPE html>
<html>
<head>
<title>Brush Selection Demo</title>
<style>
body { font-family: sans-serif; padding: 20px; background: #f5f5f5; }
svg { background: white; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
.dot { fill: #4ecdc4; stroke: #fff; stroke-width: 1; }
.dot.selected { fill: #ff6b35; }
.selection { fill: #4ecdc4; fill-opacity: 0.15; stroke: #4ecdc4; }
#info { margin-top: 10px; font-size: 14px; color: #666; }
#clear { padding: 6px 12px; cursor: pointer; background: #ff6b35; border: none; color: white; border-radius: 4px; margin-left: 10px; }
</style>
</head>
<body>
<h2>Brush to Select Points</h2>
<svg width="600" height="400" id="chart"></svg>
<div id="info">Drag to select points <button id="clear">Clear</button></div>
<script src="https://d3js.org/d3.v7.min.js"></script>
<script>
var width = 600, height = 400;
var svg = d3.select('#chart');
var data = d3.range(100).map(function() {
return { x: Math.random() * width, y: Math.random() * height };
});
svg.selectAll('circle')
.data(data).enter()
.append('circle').attr('class', 'dot')
.attr('cx', function(d) { return d.x; })
.attr('cy', function(d) { return d.y; })
.attr('r', 4);
var brush = d3.brush()
.extent([[0, 0], [width, height]])
.on('end', function(event) {
if (!event.selection) {
svg.selectAll('.dot').attr('class', 'dot');
d3.select('#info').text('No selection');
return;
}
var [[x0, y0], [x1, y1]] = event.selection;
svg.selectAll('.dot')
.attr('class', function(d) {
return (d.x >= x0 && d.x <= x1 && d.y >= y0 && d.y <= y1)
? 'dot selected' : 'dot';
});
var count = svg.selectAll('.selected').size();
d3.select('#info').text('Selected: ' + count + ' points');
});
svg.append('g').call(brush);
d3.select('#clear').on('click', function() {
svg.select('.brush').call(brush.move, null);
});
</script>
</body>
</html>
What's Next
Implement drag and drop behavior.
Drag Drop — Drag and drop in D3.js. Color Scales — Color scales and schemes.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro