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