【问题标题】:How to determine if D3 tree node falls outside SVG container如何确定 D3 树节点是否落在 SVG 容器之外
【发布时间】:2016-12-23 08:39:02
【问题描述】:

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

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

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

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

Getting Screen Positions of D3 Nodes After Transform

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

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 新手,所以我可能做错了什么,但是什么?或者也许有更好的方法?

【问题讨论】:

    标签: d3.js svg tree position


    【解决方案1】:

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

    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 在 cmets 中指出,我的数学错了,应该是:

    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;
    }
    

    【讨论】:

    • 似乎有效,但缩放后无效。坐标太大了,一定是比例计算的问题。
    • 这似乎可以完成这项工作:coords = { x: trans[0] * scaleParent[0] + transParent[0], y: trans[1] * scaleParent[1] + transParent[1] };
    • @Christian,哎呀,我的错。谢谢你抓住那个。为了后代,我已经用你更正的数学更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-29
    • 1970-01-01
    • 2014-01-17
    • 1970-01-01
    相关资源
    最近更新 更多