在d3中调用一个函数来提供.attr()

xtfmy6hx  于 2023-10-19  发布在  其他
关注(0)|答案(2)|浏览(110)

我有.attr,它在d3中创建了我的链接路径,如下所示,demo中的第42行:

link.each(function (d){})
  .attr('x1', function (d) {
    return d.source.x;
  })
  .attr('y1', function (d) {
    return d.source.y;
  })
  .attr('x2', function (d) {
    return d.target.x;
  })
  .attr('y2', function (d) {
    return d.target.y;
  });

以上是我的路径链接。我已经改变了这一点,以计算使链接路径更小。然而,有很多重复的逻辑,不知道如何调用函数来返回所需的值。具体如下:

link.attr("x1", function(d) {
      // Total difference in x and y from source to target
      let diffX = d.target.x - d.source.x;
      let diffY = d.target.y - d.source.y;

      // Length of path from center of source node to center of target node
      let pathLength = Math.sqrt((diffX * diffX) + (diffY * diffY));

      // x and y distances from center to outside edge of target node
      let offsetX = (diffX * 40) / pathLength;
      return d.source.x + offsetX;
    }).attr("y1", function(d) {
      let diffX = d.target.x - d.source.x;
      let diffY = d.target.y - d.source.y;

      let pathLength = Math.sqrt((diffX * diffX) + (diffY * diffY));

      let offsetY = (diffY * 40) / pathLength;

      return d.source.y + offsetY;
    }).attr("x2", function(d) {
      let diffX = d.target.x - d.source.x;
      let diffY = d.target.y - d.source.y;

      let pathLength = Math.sqrt((diffX * diffX) + (diffY * diffY));

      let offsetX = (diffX * 40) / pathLength;

      return d.target.x - offsetX;
    }).attr("y2", function(d) {
      let diffX = d.target.x - d.source.x;
      let diffY = d.target.y - d.source.y;

      let pathLength = Math.sqrt((diffX * diffX) + (diffY * diffY));

      let offsetY = (diffY * 40) / pathLength;

      return d.target.y - offsetY;
    })

对于d.source.x/d.target.x值,它返回offsetX,对于d.source.y/d.target.y值,它返回offsetY
理想情况下,我不希望所有这些重复的逻辑,并尝试在进入函数的链接上做.call(),但我不知道如何将结果返回到属性本身,例如。

.attr('x1', function (d) {
    return d.source.x; //function return from .call()
  })

我也试过把函数调用放在上面的属性中,但得到一个错误“不是函数”,例如

.attr('x1', function (d) {
    return this.myNewPathFunction(d); 
  })

demo中的第42行

50few1ms

50few1ms1#

您的目标是编写更少的重复代码行减少所需的计算量。
一个惯用的D3解决方案是使用selection.each();
因此,在你的情况下:

link.each(d, i, n) {
  // Total difference in x and y from source to target
  let diffX = d.target.x - d.source.x;
  let diffY = d.target.y - d.source.y;

  // Length of path from center of source node to center of target node
  let pathLength = Math.sqrt(diffX * diffX + diffY * diffY);

  // x and y distances from center to outside edge of target node
  let offsetX = (diffX * 40) / pathLength;
  let offsetY = (diffY * 40) / pathLength;

  d3.select(n[i])
    .attr("x1", d.source.x + offsetX)
    .attr("y1", d.source.y + offsetY)
    .attr("x2", d.target.x - offsetX)
    .attr("y2", d.target.y - offsetY);
};

注意offsetXoffsetY的计算在每个元素中只发生一次。在你的特定情况下,这不是一个沉重的计算,但当它是一个好主意,减少浏览器的负担。

icnyk63a

icnyk63a2#

你可以把move your logic转换成这样的函数:

const coordinate = (position, d, index, nodes) => {
  // Total difference in x and y from source to target
  let diffX = d.target.x - d.source.x;
  let diffY = d.target.y - d.source.y;

  // Length of path from center of source node to center of target node
  let pathLength = Math.sqrt(diffX * diffX + diffY * diffY);

  // x and y distances from center to outside edge of target node
  let offsetX = (diffX * 40) / pathLength;
  let offsetY = (diffY * 40) / pathLength;

  if (position === 'x1') return d.source.x + offsetX;
  if (position === 'y1') return d.source.y + offsetY;
  if (position === 'x2') return d.target.x - offsetX;
  if (position === 'y2') return d.target.y - offsetY;
};

link
  .attr('x1', (d, i, nodes) => coordinate('x1', d, i, nodes))
  .attr('y1', (d, i, nodes) => coordinate('y1', d, i, nodes))
  .attr('x2', (d, i, nodes) => coordinate('x2', d, i, nodes))
  .attr('y2', (d, i, nodes) => coordinate('y2', d, i, nodes));

相关问题