D3.js 选择器 #
选择器是 D3.js 的核心功能之一,它提供了一种强大而灵活的方式来选择和操作 DOM 元素。D3 的选择器 API 类似于 jQuery,但针对数据可视化进行了优化。
选择器基础 #
核心概念 #
text
┌─────────────────────────────────────────────────────────────┐
│ D3 选择器工作流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 选择元素 ──► 修改属性 ──► 绑定数据 ──► 更新视图 │
│ │
│ d3.select() .attr() .data() .enter()/exit() │
│ │
└─────────────────────────────────────────────────────────────┘
选择元素 #
select - 选择单个元素 #
选择第一个匹配的元素:
javascript
d3.select('body');
d3.select('#chart');
d3.select('.container');
d3.select('div.bar');
d3.select('svg > rect');
selectAll - 选择多个元素 #
选择所有匹配的元素:
javascript
d3.selectAll('p');
d3.selectAll('.bar');
d3.selectAll('circle');
d3.selectAll('svg > g > rect');
选择器组合 #
javascript
const svg = d3.select('#chart')
.append('svg');
const bars = svg.selectAll('.bar');
const firstCircle = d3.select('svg')
.select('circle');
选择器方法 #
selection.select() #
在当前选择中查找后代元素:
javascript
const svg = d3.select('#chart');
const rect = svg.select('rect');
const allRects = svg.selectAll('rect');
selection.selectAll() #
选择所有后代元素:
javascript
const svg = d3.select('svg');
const circles = svg.selectAll('circle');
const groups = svg.selectAll('g.bar');
selection.filter() #
过滤选择:
javascript
d3.selectAll('circle')
.filter('.active')
.attr('fill', 'red');
d3.selectAll('circle')
.filter(d => d.value > 100)
.attr('fill', 'orange');
d3.selectAll('circle')
.filter(function() {
return this.getAttribute('r') > 10;
});
selection.merge() #
合并两个选择:
javascript
const circles = svg.selectAll('circle')
.data(data);
circles.enter()
.append('circle')
.merge(circles)
.attr('fill', 'steelblue');
操作属性 #
selection.attr() #
设置或获取属性:
javascript
d3.select('svg')
.attr('width', 500)
.attr('height', 300);
d3.select('circle')
.attr('cx', 100)
.attr('cy', 150)
.attr('r', 20);
const width = d3.select('svg').attr('width');
d3.selectAll('circle')
.attr('r', (d, i) => 5 + i * 2);
d3.selectAll('rect')
.attr('x', d => xScale(d.x))
.attr('y', d => yScale(d.y));
selection.style() #
设置或获取样式:
javascript
d3.select('div')
.style('color', 'red')
.style('font-size', '14px')
.style('background', '#f0f0f0');
const color = d3.select('div').style('color');
d3.selectAll('.bar')
.style('fill', d => colorScale(d.value));
d3.selectAll('circle')
.style('opacity', (d, i) => i % 2 ? 0.5 : 1);
selection.classed() #
添加或移除类名:
javascript
d3.select('div')
.classed('active', true);
d3.select('div')
.classed('hidden', false);
d3.selectAll('circle')
.classed('highlight', d => d.value > 100);
d3.select('div')
.classed('active highlight', true);
selection.property() #
设置或获取元素属性(非 HTML 属性):
javascript
d3.select('input')
.property('checked', true);
d3.select('input')
.property('value', 'Hello');
const checked = d3.select('checkbox').property('checked');
d3.selectAll('input[type="checkbox"]')
.property('checked', function() {
return this.checked;
});
selection.text() #
设置或获取文本内容:
javascript
d3.select('h1')
.text('Hello D3.js');
const text = d3.select('h1').text();
d3.selectAll('.label')
.text(d => d.name);
d3.selectAll('text')
.text((d, i) => `Item ${i + 1}: ${d.value}`);
selection.html() #
设置或获取 HTML 内容:
javascript
d3.select('div')
.html('<span>Hello</span>');
const html = d3.select('div').html();
d3.select('.tooltip')
.html(`<strong>${d.name}</strong>: ${d.value}`);
添加和删除元素 #
selection.append() #
在末尾添加子元素:
javascript
const svg = d3.select('#chart')
.append('svg')
.attr('width', 500)
.attr('height', 300);
svg.append('circle')
.attr('cx', 250)
.attr('cy', 150)
.attr('r', 50);
svg.append('g')
.attr('class', 'x-axis');
selection.insert() #
在指定位置插入元素:
javascript
d3.select('ul')
.insert('li', ':first-child')
.text('First');
d3.select('svg')
.insert('rect', ':first-child')
.attr('width', 100)
.attr('height', 50);
d3.select('svg')
.insert('circle', '.background')
.attr('r', 10);
selection.remove() #
删除元素:
javascript
d3.select('#old-chart').remove();
d3.selectAll('.inactive').remove();
circles.exit().remove();
selection.clone() #
克隆元素:
javascript
d3.select('circle')
.clone(true);
d3.selectAll('.bar')
.clone()
.attr('fill', 'red');
遍历选择 #
selection.each() #
遍历每个元素:
javascript
d3.selectAll('circle')
.each(function(d, i, nodes) {
console.log(d);
console.log(i);
console.log(this);
console.log(nodes);
});
d3.selectAll('.bar')
.each(function(d) {
d3.select(this)
.attr('x', d.x)
.attr('y', d.y);
});
selection.call() #
调用函数并传递选择:
javascript
function setColor(selection, color) {
selection.style('color', color);
}
d3.selectAll('text')
.call(setColor, 'red');
d3.selectAll('circle')
.call(selection => {
selection
.attr('r', 5)
.attr('fill', 'steelblue');
});
selection.nodes() #
获取选择中的所有节点:
javascript
const nodes = d3.selectAll('circle').nodes();
nodes.forEach(node => {
console.log(node.getAttribute('cx'));
});
selection.node() #
获取第一个节点:
javascript
const firstCircle = d3.select('circle').node();
const svg = d3.select('svg').node();
const width = svg.clientWidth;
selection.size() #
获取选择中的元素数量:
javascript
const count = d3.selectAll('circle').size();
console.log(`共有 ${count} 个圆形`);
selection.empty() #
检查选择是否为空:
javascript
if (d3.select('#chart').empty()) {
console.log('没有找到元素');
}
选择器链式调用 #
D3 选择器支持链式调用,使代码更加简洁:
javascript
d3.select('#chart')
.append('svg')
.attr('width', 500)
.attr('height', 300)
.append('g')
.attr('transform', 'translate(50, 50)')
.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', d => xScale(d.x))
.attr('cy', d => yScale(d.y))
.attr('r', 5)
.attr('fill', 'steelblue')
.attr('stroke', '#333')
.attr('stroke-width', 1);
选择器与数据 #
结合数据使用 #
javascript
const data = [
{ name: 'A', value: 10 },
{ name: 'B', value: 20 },
{ name: 'C', value: 30 }
];
d3.select('svg')
.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', (d, i) => i * 50 + 50)
.attr('cy', d => 150 - d.value * 3)
.attr('r', d => d.value)
.attr('fill', 'steelblue');
回调函数参数 #
javascript
d3.selectAll('.bar')
.attr('x', function(d, i, nodes) {
return d.x;
})
.attr('y', function(d, i, nodes) {
console.log(`索引: ${i}`);
console.log(`节点数量: ${nodes.length}`);
return d.y;
});
高级选择技巧 #
选择父元素 #
javascript
const parent = d3.select('circle').select(function() {
return this.parentNode;
});
选择兄弟元素 #
javascript
d3.selectAll('circle')
.filter(function() {
return this.previousElementSibling;
});
选择特定索引 #
javascript
d3.selectAll('circle')
.filter((d, i) => i === 0)
.attr('fill', 'red');
d3.selectAll('circle')
.filter((d, i) => i % 2 === 0)
.attr('fill', 'blue');
选择第一个和最后一个 #
javascript
d3.select('circle:first-child');
d3.select('circle:last-child');
d3.selectAll('circle')
.filter(':first-child');
选择器与命名空间 #
创建带命名空间的元素 #
javascript
const svg = d3.select('body')
.append(d3.namespaces.svg)
.attr('width', 500);
const xlink = d3.namespaces.xlink;
选择器最佳实践 #
1. 缓存选择 #
javascript
const svg = d3.select('#chart svg');
const circles = svg.selectAll('circle');
circles.attr('fill', 'steelblue');
circles.attr('stroke', '#333');
2. 使用有意义的类名 #
javascript
d3.selectAll('.data-point')
.classed('selected', d => d.selected);
3. 避免过度选择 #
javascript
const chart = d3.select('#chart');
chart.select('svg')
.attr('width', 500);
chart.select('.title')
.text('My Chart');
4. 使用选择器分组 #
javascript
const g = svg.append('g')
.attr('class', 'bars');
g.selectAll('rect')
.data(data)
.enter()
.append('rect');
常见问题 #
1. 选择不到元素 #
javascript
d3.select('#nonexistent');
d3.select('#nonexistent').empty();
d3.select('#nonexistent').node();
2. 链式调用中断 #
javascript
const svg = d3.select('#chart')
.append('svg');
svg.append('circle');
svg.append('rect');
3. 数据绑定后选择 #
javascript
const update = svg.selectAll('circle')
.data(data, d => d.id);
update.enter()
.append('circle');
update.exit()
.remove();
update
.attr('fill', 'steelblue');
选择器方法速查表 #
| 方法 | 描述 | 示例 |
|---|---|---|
| select | 选择单个元素 | d3.select('#chart') |
| selectAll | 选择多个元素 | d3.selectAll('circle') |
| attr | 设置/获取属性 | .attr('width', 500) |
| style | 设置/获取样式 | .style('color', 'red') |
| classed | 添加/移除类名 | .classed('active', true) |
| property | 设置/获取属性 | .property('checked', true) |
| text | 设置/获取文本 | .text('Hello') |
| html | 设置/获取HTML | .html('<span>Hi</span>') |
| append | 添加子元素 | .append('circle') |
| insert | 插入元素 | .insert('rect', ':first-child') |
| remove | 删除元素 | .remove() |
| clone | 克隆元素 | .clone(true) |
| each | 遍历元素 | .each(function(d) { }) |
| call | 调用函数 | .call(setColor, 'red') |
| filter | 过滤选择 | .filter('.active') |
| merge | 合并选择 | .merge(selection) |
| nodes | 获取所有节点 | .nodes() |
| node | 获取第一个节点 | .node() |
| size | 获取元素数量 | .size() |
| empty | 检查是否为空 | .empty() |
下一步 #
现在你已经掌握了 D3.js 选择器的使用,接下来学习 数据绑定,了解如何将数据与 DOM 元素关联!
最后更新:2026-03-28