You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在D3.js的.join()的enter回调中访问绑定数据?

解决D3.js join() enter回调中访问绑定数据的问题

问题场景

在使用D3.js的.join()方法时,需要在enter回调中访问每个元素绑定的数据(其中的n字段)来创建Rects实例,但调用.datum()方法只能获取到选择集第一个元素的数据,导致所有enter元素都复用同一个n值。已知Rects类无法修改,需要调整enter回调的逻辑。

解决方案

.datum()方法仅返回选择集第一个元素的绑定数据,而enter选择集包含多个待处理元素。要为每个元素单独处理对应的数据,需使用.each()方法遍历enter选择集,在遍历回调中访问当前元素的绑定数据,再创建对应的Rects实例。

修改后的代码

JavaScript代码

class Rects {
  #n;
  #colorMap = d3.scaleOrdinal();
  #domain;
  constructor(n) {
    this.#n = n;
    this.#domain = [...Array(n)].map((_, i) => i);
    this.#colorMap
      .domain(this.#domain)
      .range(['purple', 'forestgreen', 'orange']);
  }
  
  draw(selection) {
    const height = 20,
      width = 20,
      margin = 20;
    selection.append('svg')
      .attr('width', this.#n * width + margin)
      .attr('height', height)
      .append('g')
      .attr('transform', 'translate(' + margin + ',0)')
      .selectAll('rect')
      .data(this.#domain)
      .join('rect')
      .attr('x', (i) => width * i)
      .attr('height', height)
      .attr('width', width)
      .attr('fill', (d) => this.#colorMap(d))
  }
}  

const data = [{n: 3, text: 'some text'}, {n:2, text: 'some other text'}];

d3.select('#root')
  .selectAll('li')
  .data(data)
  .join((enter) => {
    // 遍历每个enter元素,单独处理对应的数据
    return enter.each(function(d) {
      const rectInstance = new Rects(d.n);
      d3.select(this)
        .append('li')
        .text(`There should be \`d.n=${d.n}\` rects:`)
        .call(rectInstance.draw.bind(rectInstance));
    });
  })

HTML代码

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script>
<ul id="root">
</ul>

关键修改说明

  • 使用.each()遍历enter选择集中的每个元素,确保每个元素都能获取到自身绑定的数据
  • 在.each()回调中,参数d直接对应当前元素的绑定数据,可直接提取d.n创建Rects实例
  • 通过d3.select(this)获取当前元素的选择集,后续的元素添加和方法调用都基于该单个元素,保证每个<li>对应正确数量的矩形

内容的提问来源于stack exchange,提问作者thothal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 16:27:25