如何确定 D3 树节点是否落在 SVG 容器之外

How to determine if D3 tree node falls outside SVG container

我正在使用 D3 树布局的这个实现:

http://bl.ocks.org/robschmuecker/7880033

我已经让我的树响应外部事件,为此,我想知道某个节点当前是否不可见(在 svg 容器之外),以便我可以重新居中它。

经过一些研究,我发现了这个 SO 答案,它看起来正是我需要的:

Getting Screen Positions of D3 Nodes After Transform

当拖动左上角的节点并点击它时,我希望坐标为[0,0]。 但由于某种原因,x 坐标总是有相当大的偏移量是错误的。 在这里做了一个fiddle:

https://jsfiddle.net/syberyan/yd8L4v0q/

我修改了 click() 函数,让它打印目标节点的坐标。

function getElementCoords(element, coords) {
    var ctm = element.getCTM(),
    x = ctm.e + coords.x*ctm.a + coords.y*ctm.c,
    y = ctm.f + coords.x*ctm.b + coords.y*ctm.d;
    return {x: x, y: y};
};

function click(d) {
    if (d3.event.defaultPrevented) return; // click suppressed
    d3.selectAll('.node').each(function (node, i) {
    if (d === node) {
      let coords = getElementCoords(this, node);
      console.log(coords.x, coords.y); // shows coords relative to my svg container
    }
  });
}

我是 D3 新手所以我可能做错了什么,但是什么?或者也许有更好的方法?

我没有仔细查看链接的问题或您当前的计算。相反,我认为计算可以简化为:

function getElementCoords(element) {      
  // translate on node
  var trans = d3.transform(d3.select(element).attr('transform')).translate,
      // transform on parent "zoom" container
      transFormParent = d3.transform(d3.select(element.parentNode).attr('transform')),
      // translate on zoom container
      transParent = transFormParent.translate,
      // scale on zoom container
      scaleParent = transFormParent.scale,
      // final position of node
      pos = {
        x: trans[0] + transParent[0]/scaleParent[0],
        y: trans[1] + transParent[1]/scaleParent[1]
      };

    return pos;
}

称其为:

function click(d) {
  console.log(getElementCoords(this));
}

已更新 fiddle

编辑

@Christian 在评论中指出,我的数学不对,应该是:

function getElementCoords(element) {      
  // translate on node
  var trans = d3.transform(d3.select(element).attr('transform')).translate,
      // transform on parent "zoom" container
      transFormParent = d3.transform(d3.select(element.parentNode).attr('transform')),
      // translate on zoom container
      transParent = transFormParent.translate,
      // scale on zoom container
      scaleParent = transFormParent.scale,
      // final position of node
      pos = {
        x: trans[0] * scaleParent[0] + transParent[0], 
        y: trans[1] * scaleParent[1] + transParent[1]
      };

    return pos;
}