如何在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
相关产品推荐
相关产品推荐

