我在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
类来删除节点,但这并不是最有效的方法,而且我在尝试实现它时遇到了一些麻烦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';
}
})
或者可能有另一种更好的解决方法。
我该怎么办?
只需将pointer-events: none;
设置为这些标签:
.nonselectable {
pointer-events: none;
etc...
}
实际上,由于我看到标签不可点击,你可以将pointer-events: none;
设置为所有标签。
这是更新的JSFiddle:qazxsw poi