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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 05:24:07