简体   繁体   English

D3 叶节点 - 许多元素重叠

[英]D3 Leaf Nodes - many elements overlaps

i'm using D3JS in the following JSFiddle Example: HERE我在以下 JSFiddle 示例中使用 D3JS:这里

I'm experiencing a strange issue: when i have a lot of leaf nodes on my graph, the leafs overlaps between them, currently, i've tried to use many strategies to go (like the .separation(function(a, b) { return (a.parent == b.parent ? 1 : 5 ) }) ) on the nodes but with no luck.我遇到了一个奇怪的问题:当我的图上有很多叶节点时,它们之间的叶节点重叠,目前,我尝试使用许多策略(例如.separation(function(a, b) { return (a.parent == b.parent ? 1 : 5 ) }) ) 在节点上,但没有运气。

Take note that i can have a D3 Charts with 500/600 leaf nodes and them must be readable.请注意,我可以拥有一个包含 500/600 个叶节点的 D3 图表,并且它们必须是可读的。

My goal is to increase the space between the leaf nodes and make them readable and not overlapped, how i can do that?我的目标是增加叶节点之间的空间并使它们可读且不重叠,我该怎么做?

The tree and cluster layouts will do a separation based on the available space.树和集群布局将根据可用空间进行分离。 Therefore, that value you passed is not an absolute value (in pixels, for instance), but just a proportion.因此,您传递的值不是绝对值(例如,以像素为单位),而只是一个比例。

You have to tell D3 how much SVG height (or width) you need.您必须告诉 D3 您需要多少 SVG 高度(或宽度)。 For instance, you can calculate the number of leaves in the root ...例如,您可以计算root的叶子数...

var numberOfLeaves = countLeaves(root);

function countLeaves(obj) {
  var leaves = 0;
  recursiveCounter(obj);
  function recursiveCounter(obj) {
    if (obj.children) {
      for (var i = 0; i < obj.children.length; i++) {
        if (obj.children[i].children) {
          recursiveCounter(obj.children[i]);
        } else {
          leaves++;
        };
      };
    };
  }
  return leaves;
};

And change the width accordingly:并相应地更改宽度:

var nodeHeight = 12;

height = nodeHeight * numberOfLeaves;

Here is the code with that change:这是具有该更改的代码:

 var width = 1000, height = 1000; var diameter = 300; var duration = 2000; d3.selectAll("input").on("change", change); function change() { if (this.value === "radialtree") transitionToRadialTree(); else if (this.value === "radialcluster") transitionToRadialCluster(); else if (this.value === "tree") transitionToTree(); else transitionToCluster(); }; function transitionToRadialTree() { var nodes = radialTree.nodes(root), // recalculate layout links = radialTree.links(nodes); svg.transition().duration(duration) .attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")"); // set appropriate translation (origin in middle of svg) link.data(links) .transition() .duration(duration) .style("stroke", "#fc8d62") .attr("d", radialDiagonal); //get the new radial path node.data(nodes) .transition() .duration(duration) .attr("transform", function(d) { return "rotate(" + (dx - 90) + ")translate(" + dy + ")"; }); node.select("circle") .transition() .duration(duration) .style("stroke", "#984ea3"); }; function transitionToRadialCluster() { var nodes = radialCluster.nodes(root), // recalculate layout links = radialCluster.links(nodes); svg.transition().duration(duration) .attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")"); // set appropriate translation (origin in middle of svg) link.data(links) .transition() .duration(duration) .style("stroke", "#66c2a5") .attr("d", radialDiagonal); //get the new radial path node.data(nodes) .transition() .duration(duration) .attr("transform", function(d) { return "rotate(" + (dx - 90) + ")translate(" + dy + ")"; }); node.select("circle") .transition() .duration(duration) .style("stroke", "#4daf4a"); }; function transitionToTree() { var nodes = tree.nodes(root), //recalculate layout links = tree.links(nodes); svg.transition().duration(duration) .attr("transform", "translate(40,0)"); link.data(links) .transition() .duration(duration) .style("stroke", "#e78ac3") .attr("d", diagonal); // get the new tree path node.data(nodes) .transition() .duration(duration) .attr("transform", function(d) { return "translate(" + dy + "," + dx + ")"; }); node.select("circle") .transition() .duration(duration) .style("stroke", "#377eb8"); }; function transitionToCluster() { var nodes = cluster.nodes(root), //recalculate layout links = cluster.links(nodes); svg.transition().duration(duration) .attr("transform", "translate(40,0)"); link.data(links) .transition() .duration(duration) .style("stroke", "#8da0cb") .attr("d", diagonal); //get the new cluster path node.data(nodes) .transition() .duration(duration) .attr("transform", function(d) { return "translate(" + dy + "," + dx + ")"; }); node.select("circle") .transition() .duration(duration) .style("stroke", "#e41a1c"); }; var root = getData(); var nodeHeight = 12; var numberOfLeaves = countLeaves(root); function countLeaves(obj) { var leaves = 0; recursiveCounter(obj); function recursiveCounter(obj) { if (obj.children) { for (var i = 0; i < obj.children.length; i++) { if (obj.children[i].children) { recursiveCounter(obj.children[i]); } else { leaves++; }; }; }; } return leaves; }; height = nodeHeight * numberOfLeaves; var tree = d3.layout.tree() .separation(function(a, b) { return (a.parent == b.parent ? 1 : 5) }) .size([height, width - 160]); var cluster = d3.layout.cluster() .separation(function(a, b) { return (a.parent == b.parent ? 1 : 5) }) .size([height, width - 160]); var diagonal = d3.svg.diagonal() .projection(function(d) { return [dy, dx]; }); var radialTree = d3.layout.tree() .size([360, diameter / 2]) .separation(function(a, b) { return (a.parent == b.parent ? 1 : 5) / a.depth; }); var radialCluster = d3.layout.cluster() .size([360, diameter / 2]) .separation(function(a, b) { return (a.parent == b.parent ? 1 : 5) / a.depth; }); var radialDiagonal = d3.svg.diagonal.radial() .projection(function(d) { return [dy, dx / 180 * Math.PI]; }); function responsivefy(svg) { // get container + svg aspect ratio var container = d3.select(svg.node().parentNode), width = parseInt(svg.style("width")), height = parseInt(svg.style("height")), aspect = width / height; // add viewBox and preserveAspectRatio properties, // and call resize so that svg resizes on inital page load svg.attr("viewBox", "0 0 " + width + " " + height) .attr("preserveAspectRatio", "xMinYMid") .call(resize); // to register multiple listeners for same event type, // you need to add namespace, ie, 'click.foo' // necessary if you call invoke this function for multiple svgs // api docs: https://github.com/mbostock/d3/wiki/Selections#on d3.select(window).on("resize." + container.attr("id"), resize); // get width of container and resize svg to fit it function resize() { var targetWidth = parseInt(container.style("width")); svg.attr("width", targetWidth); svg.attr("height", Math.round(targetWidth / aspect)); } } var nodes = cluster.nodes(root), links = cluster.links(nodes); var svg = d3.select("#test").append("svg") .attr("width", width) .attr("height", height) .call(responsivefy) .append("g") .attr("transform", "translate(40,0)"); var link = svg.selectAll(".link") .data(links) .enter() .append("path") .attr("class", "link") .style("stroke", "#8da0cb") .attr("d", diagonal); var node = svg.selectAll(".node") .data(nodes) .enter() .append("g") .attr("class", "node") .attr("transform", function(d) { return "translate(" + dy + "," + dx + ")"; }); node.append("circle") .attr("r", 4.5) .style("stroke", "#e41a1c"); node.append("text") .attr("dx", function(d) { return d.children ? -8 : 8; }) .attr("dy", 3) .style("text-anchor", function(d) { return d.children ? "end" : "start"; }) .text(function(d) { return d.name; }); function getData() { return { "name": "This Instance", "children": [{ "name": "TEST", "children": [{ "name": "FM Sala 1 [L1] AC Sala 1 [L2] FM Open Space [L3]", "children": [{ "name": "VLN1" }, { "name": "VLN2" }, { "name": "VLN3" }, { "name": "VLN_AVG" }, { "name": "VL1-2" }, { "name": "VL2-3" }, { "name": "VL3-1" }, { "name": "VLL_AVG" }, { "name": "IL1" }, { "name": "IL2" }, { "name": "IL3" }, { "name": "IL_AVG" }, { "name": "PL1" }, { "name": "PL2" }, { "name": "PL3" }, { "name": "PL_SUM" }, { "name": "QL1" }, { "name": "QL2" }, { "name": "QL3" }, { "name": "QL_SUM" }, { "name": "SL1" }, { "name": "SL2" }, { "name": "SL3" }, { "name": "SL_SUM" }, { "name": "Cos_L1" }, { "name": "Cos_L2" }, { "name": "Cos_L3" }, { "name": "Cos_LSUM" }, { "name": "kWh_L1" }, { "name": "kWh_L2" }, { "name": "kWh_L3" }, { "name": "KVARh_L1" }, { "name": "KVARh_L2" }, { "name": "KVARh_L3" }, { "name": "KVARh_LSUM" }, { "name": "KVAh_L1" }, { "name": "KVAh_L2" }, { "name": "KVAh_L3" }, { "name": "KVAh_LSUM" }] }, { "name": "Luci Open Space [L-1-2-3]", "children": [{ "name": "VLN1" }, { "name": "VLN2" }, { "name": "VLN3" }, { "name": "VLN_AVG" }, { "name": "VL1-2" }, { "name": "VL2-3" }, { "name": "VL3-1" }, { "name": "VLL_AVG" }, { "name": "IL1" }, { "name": "IL2" }, { "name": "IL3" }, { "name": "IL_AVG" }, { "name": "PL1" }, { "name": "PL2" }, { "name": "PL3" }, { "name": "QL3" }, { "name": "QL1" }, { "name": "QL2" }, { "name": "QL_SUM" }, { "name": "SL1" }, { "name": "SL2" }, { "name": "SL3" }, { "name": "SL_SUM" }, { "name": "Cos_L1" }, { "name": "Cos_L2" }, { "name": "Cos_L3" }, { "name": "Cos_LSUM" }, { "name": "PL_SUM" }, { "name": "kWh_L1" }, { "name": "kWh_L2" }, { "name": "kWh_L3" }, { "name": "KVAh_L1" }, { "name": "KVAh_L2" }, { "name": "KVAh_L3" }, { "name": "KVAh_LSUM" }, { "name": "KVARh_LSUM" }, { "name": "KVARh_L3" }, { "name": "KVARh_L2" }, { "name": "KVARh_L1" }] }, { "name": "Centrale Termica [L1-2-3]", "children": [{ "name": "VLN1" }, { "name": "VLN2" }, { "name": "VLN3" }, { "name": "VLN_AVG" }, { "name": "VL1-2" }, { "name": "VL2-3" }, { "name": "VL3-1" }, { "name": "VLL_AVG" }, { "name": "IL1" }, { "name": "IL2" }, { "name": "IL3" }, { "name": "IL_AVG" }, { "name": "PL1" }, { "name": "PL2" }, { "name": "PL3" }, { "name": "QL3" }, { "name": "QL1" }, { "name": "QL2" }, { "name": "QL_SUM" }, { "name": "SL1" }, { "name": "SL2" }, { "name": "SL3" }, { "name": "SL_SUM" }, { "name": "Cos_L1" }, { "name": "Cos_L2" }, { "name": "Cos_L3" }, { "name": "Cos_LSUM" }, { "name": "PL_SUM" }, { "name": "kWh_L1" }, { "name": "kWh_L2" }, { "name": "kWh_L3" }, { "name": "KVAh_L1" }, { "name": "KVAh_L2" }, { "name": "KVAh_L3" }, { "name": "KVAh_LSUM" }, { "name": "KVARh_LSUM" }, { "name": "KVARh_L3" }, { "name": "KVARh_L2" }, { "name": "KVARh_L1" }] }, { "name": "UPS Rack Main [L3]", "children": [{ "name": "VLN1" }, { "name": "VLN2" }, { "name": "VLN3" }, { "name": "VLN_AVG" }, { "name": "VL1-2" }, { "name": "VL2-3" }, { "name": "VL3-1" }, { "name": "VLL_AVG" }, { "name": "IL1" }, { "name": "IL2" }, { "name": "IL3" }, { "name": "IL_AVG" }, { "name": "PL1" }, { "name": "PL2" }, { "name": "PL3" }, { "name": "QL3" }, { "name": "QL1" }, { "name": "QL2" }, { "name": "QL_SUM" }, { "name": "SL1" }, { "name": "SL2" }, { "name": "SL3" }, { "name": "SL_SUM" }, { "name": "Cos_L1" }, { "name": "Cos_L2" }, { "name": "Cos_L3" }, { "name": "Cos_LSUM" }, { "name": "PL_SUM" }, { "name": "kWh_L1" }, { "name": "kWh_L2" }, { "name": "kWh_L3" }, { "name": "KVAh_L1" }, { "name": "KVAh_L2" }, { "name": "KVAh_L3" }, { "name": "KVAh_LSUM" }, { "name": "KVARh_LSUM" }, { "name": "KVARh_L3" }, { "name": "KVARh_L2" }, { "name": "KVARh_L1" }] }, { "name": "Generale [L-1-2-3]", "children": [{ "name": "VLN1" }, { "name": "VLN2" }, { "name": "VLN3" }, { "name": "VLN_AVG" }, { "name": "VL1-2" }, { "name": "VL2-3" }, { "name": "VL3-1" }, { "name": "VLL_AVG" }, { "name": "IL1" }, { "name": "IL2" }, { "name": "IL3" }, { "name": "IL_AVG" }, { "name": "PL1" }, { "name": "PL2" }, { "name": "PL3" }, { "name": "QL3" }, { "name": "QL1" }, { "name": "QL2" }, { "name": "QL_SUM" }, { "name": "SL1" }, { "name": "SL2" }, { "name": "SL3" }, { "name": "SL_SUM" }, { "name": "Cos_L1" }, { "name": "Cos_L2" }, { "name": "Cos_L3" }, { "name": "Cos_LSUM" }, { "name": "PL_SUM" }, { "name": "kWh_L1" }, { "name": "kWh_L2" }, { "name": "kWh_L3" }, { "name": "KVAh_L1" }, { "name": "KVAh_L2" }, { "name": "KVAh_L3" }, { "name": "KVAh_LSUM" }, { "name": "KVARh_LSUM" }, { "name": "KVARh_L3" }, { "name": "KVARh_L2" }, { "name": "KVARh_L1" }] }, { "name": "open space", "children": [{ "name": "dbm" }] }, { "name": "Luxmetro reception", "children": [{ "name": "lux" }] }, { "name": "Gathered - Gate 1", "children": [{ "name": "people_count" }] }] }, { "name": "test", "children": [{ "name": "Open Space", "children": [{ "name": "carbon_oxide" }] }] }] }; }
 label { font: 12px sans-serif; } .node circle { fill: #fff; stroke: steelblue; stroke-width: 1.5px; } .node { font: 10px sans-serif; } .link { fill: none; stroke: tan; stroke-width: 1.5px; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script> <form> <label><input type="radio" name="mode" value="radialtree">Radial Tree</label> <label><input type="radio" name="mode" value="radialcluster">Radial Cluster</label> <label><input type="radio" name="mode" value="tree">Tree</label> <label><input type="radio" name="mode" value="cluster" checked>Cluster</label> </form> <div id="test"> </div>

You have to do a similar math for the diameter .您必须对diameter进行类似的计算。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM