D3:如何向selection.join()内的attr属性函数传递额外参数
问题原因
你之前的写法无法实现累加是因为offset是Number类型的基础值,按值传递给foo函数时,函数内部修改的只是参数副本,外部的offset变量不会被改变,所以每次调用foo拿到的offset始终是初始值0。
可行解决方案
我们可以通过闭包维护累加状态的方式实现逻辑抽离,不需要手动传递offset和this上下文,D3会自动为attr的回调绑定当前DOM元素作为this指向。
第一步:抽离公共函数
// 抽离不需要状态的bar函数,this会被D3自动绑定为当前DOM节点 const bar = function() { return `translate(${(0 - nodeWidth(this)) / 2}, 129.6484)`; }; // 工厂函数:每次调用生成一个带独立offset状态的回调 const createFoo = () => { let offset = 0; // 返回的回调通过闭包访问上面的offset变量 return function(d, i, nodes) { const currentX = offset; offset += nodeWidth(nodes[i]) + 10; return `translate(${currentX}, 0)`; }; };
第二步:在join分支中直接调用
const toolTip = selection .selectAll('g') .data(data) .join( (enter) => { const g = enter.append('g') g.append('text') .attr('x', 17.5) .attr('y', 10) .text(d => d.text); g.attr('transform', createFoo()); selection.attr('transform', bar); }, (update) => { update.select('text') .text(d => d.text); update.attr('transform', createFoo()); selection.attr('transform', bar); } );
替代方案(引用类型传参)
如果你不想用工厂函数,也可以把offset封装为引用类型,修改引用的属性可以同步到外部:
const foo = function(d, i, nodes, offsetRef) { const currentX = offsetRef.value; offsetRef.value += nodeWidth(nodes[i]) + 10; return `translate(${currentX}, 0)`; }; // 调用方式 let offsetRef = {value: 0}; update.attr('transform', (d, i, nodes) => foo(d, i, nodes, offsetRef));
内容的提问来源于stack exchange,提问作者floatingpurr
相关产品推荐
相关产品推荐

