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

问题描述 投票:1回答:1

我在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';
    }
})

或者可能有另一种更好的解决方法。

我该怎么办?

javascript d3.js svg
1个回答
1
投票

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

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

实际上,由于我看到标签不可点击,你可以将pointer-events: none;设置为所有标签。

这是更新的JSFiddle:qazxsw poi

© www.soinside.com 2019 - 2024. All rights reserved.