树形图-防止标签重叠节点

时间:2019-04-22 11:23:24

标签: javascript d3.js svg

我已经在d3(v5)中制作了可折叠树形图,其简化版本可以在以下位置找到:https://jsfiddle.net/philipnye/cwj9nkhr/

每个节点都有一个标签,但是标签仅在有足够空间使其不互相重叠或太靠近SVG边缘的位置显示。在链接的示例中,在第一次加载时,标签仅出现在树图的前两个深度。

requiredSpacing用于估计需要多少空间,而minSpacing则检查每个深度的节点之间存在的最小间距。

以下几行放置节点和标签,并具有过渡效果:

var nodeUpdate=nodeEnter.merge(node)
    .transition()
    .duration(function() {
        if (loaded==0) {
            return 0;
        }
        else {
            return duration;
        }
    })
    .attr("transform", function(d) {
        return "translate(" + d.x + "," + d.y + ")";
    });

nodeUpdate.select("circle")
    .attr("r", function(d) {
        return radiuses[d.depth];
    })
    .attr("class", function(d) {
        if (d._children) {
            return "filled";
        } else {
            return "unfilled";
        }
    });

nodeUpdate.select("text")
    .style("fill-opacity", function(d) {
        if (minSpacing[d.depth]<requiredSpacing[d.depth]*2 || (d.data.position=='left' && Math.ceil(d.x/5)*5-radiuses[d.depth]-requiredSpacing[d.depth]<margin.left) || (d.data.position=='right' && Math.ceil(d.x/5)*5+radiuses[d.depth]+requiredSpacing[d.depth]>width)) {
            return 1e-6;
        }
        else {
            return 1;
        }
    })
    .attr("class", function(d) {
        if (minSpacing[d.depth]<requiredSpacing[d.depth]*2 || (d.data.position=='left' && Math.ceil(d.x/5)*5-radiuses[d.depth]-requiredSpacing[d.depth]<margin.left) || (d.data.position=='right' && Math.ceil(d.x/5)*5+radiuses[d.depth]+requiredSpacing[d.depth]>width)) {
            return "nodeLabel nonselectable";
        }
        else {
            return "nodeLabel";
        }
    })

我将没有空格显示的标签的不透明度设置为1e-6(以启用过渡),并给它们提供nonselectable类,这意味着无法选择标签。但是我实际上并没有删除它们-然后我遇到的问题是,在某些情况下,它们与节点重叠,这意味着无法单击节点以展开/折叠该点以下的树。查看比标记为“男性”和“女性”的节点深两到三个级别的节点-只能单击节点的三分之一到一半之间的某个位置。 (请注意,底部层中的节点不可扩展/可折叠,因为它们没有子节点。)

如何最好地删除这些标签,或者至少停止它们以防止您单击节点?

我考虑过的事情:

  • 更改抽奖顺序可能会将标签放在“ 节点-但我认为这将涉及对 代码,我不知道如何
  • 大概有可能 随后使用nonselectable来删除节点 课,但这不是最有效的方法,我已经 实施它时遇到了一些麻烦
  • 我想将标签移到 SVG尺寸之外的某个地方可能有效-尽管我是 不知道如何在过渡中处理此问题,因此它不是 被用户看到
  • font-size设置为接近零。我试过了 将下面的代码添加到我的nodeUpdate代码中,但这似乎会导致过渡问题
.attr("font-size", function(d) {
    if (minSpacing[d.depth]<requiredSpacing[d.depth]*2 || (d.data.position=='left' && Math.ceil(d.x/5)*5-radiuses[d.depth]-requiredSpacing[d.depth]<margin.left) || (d.data.position=='right' && Math.ceil(d.x/5)*5+radiuses[d.depth]+requiredSpacing[d.depth]>width)) {
        return '0.1em';
    }
})

或者可能有另一种更好的方法来解决这个问题。

我应该怎么做?

1 个答案:

答案 0 :(得分:1)

只需为这些标签设置pointer-events: none;

.nonselectable {
    pointer-events: none;
    etc...
}

实际上,由于我看到标签不可点击,因此您可以将pointer-events: none;设置为其中的全部

这是更新的JSFidle:https://jsfiddle.net/e3j7ta4y/