0

在闪电中,我们正在使用D3js库在圆形树中显示径向树。当我们有大约15 个节点时,它看起来不错。

当我们尝试显示超过 15 条记录时,节点相互碰撞

我需要在圆圈周围显示 40 多个节点,节点之间有良好的空间。

在这里,我分享了我的代码和屏幕截图

drawTree : function(component, event, helper, treeData) {


  var textMaxLength = 0, radius = 50, circleTextLen = 0;
  // Properly formatted treeData, if it's flat data, use stratify
  console.log('treeData', treeData);
  


  var margin = { top: 10, right: 10, bottom: 10, left: 10 },
    width = 1200,
    height = 1000;

  // Prepare container

  var svg = d3.select("body")
      .append("svg")
      .attr("width", width)
      .attr("height", height),
    g = svg.append("g")
      .attr("transform",
        "translate(" + 450 + "," + 400 + ") scale(1) ");

  var i = 0,
    // duration = 750,
    cluster_size = 800,
    root;

  // Define cluster

  var cluster = d3.cluster()
    .size([cluster_size, cluster_size]);

  // Get the root

  root = d3.hierarchy(treeData, function(d) {
    return d.children;
  });
  // Collapse all children
  if(typeof collapse === 'undefined') {
    root.children.forEach(collapse);
  }


  root.x0 = 0;
  root.y0 = 0;

  // Start drawing
  draw(root);

  function draw(source) {

    var treeData = cluster(root);

    var nodes = treeData.descendants(),
      links = treeData.descendants()
        .slice(1);

    var node = g.selectAll('g.node')
      .data(nodes, function(d) {
        return d.id || (d.id = ++i);
      });

    // Enter the node, draw it at source, so that we can animate later from
    // source

    var nodeEnter = node
      .enter()
      .append('g')
      .attr('class', 'node')
      .attr("transform", function(d) {
        return "translate(" + project(source, source.x0, source.y0) + ")";
      })
      .on('click', d => {
        // d3.event.preventDefault();
        if(d.data.level == 'subnode') {
          component.set("v.nodeName", d.data.name);
        }
      })
      .on("dblclick", click);

    // Draw a circle with zero radius

    nodeEnter.append('circle')
      .attr('class', 'node')
      .attr('r', 20)
      .attr('stroke', 'steelblue')
      .attr('fill', 'white')
      .attr('stroke-width', '1.5px')
      .attr('display', function(d) {
        if(d.data.level == 'subnode' || d.data.level != 'node') {
          return 'block';
        } else {
          return 'none';
        }
      });


    //Draw text
    nodeEnter.append("text")
      //  .attr("class","wrap")
      .attr("dy", function(d) {
        if(d.data.level == 'node') {
          return '0.5em';
        } else {
          return '0.5em';
        }
      })

      .style("text-anchor", 'middle')
      .text(function(d) {
        if(textMaxLength < (d.data.name).length) {
          textMaxLength = (d.data.name).length;
        }
        return d.data.name;
      })
      //  .style("font-size", "1px")
      .call(wrap, 100)
      .each(getSize)
      .style('fill', function(d) {
       
          return "white";
        

      })
      .style("font-size", function(d) {
          return (d.scale + 10 + "px");
        
      });


    var nodeUpdate = nodeEnter.merge(node);

    // When we enter the update phase, change the coordinate of each node using a 
    // transition, so that we can animate

    nodeUpdate.transition()
      .duration(duration)
      .attr("transform", function(d) {
        return "translate(" + project(d, d.x, d.y) + ")";
      });

    // Add color to circle

    
    // Handle exit node, show a transition

    var nodeExit = node.exit()
      .transition()
      .duration(duration)
      .attr("transform", function(d) {
        return "translate(" + project(source, source.x, source.y) + ")";
      })
      .remove();

    // On exit reduce the node circles size to 0
    nodeExit.select('circle')
      .attr('r', 1e-6);

    // On exit reduce the opacity of text labels
    nodeExit.select('text')
      .style('fill-opacity', 1e-6);

    var link = g.selectAll('path.link')
      .data(links, function(d) {
        return d.id || (d.id = i);
      });
    // We need animation for links also, so we first draw paths whose start and origin is 
    // same
    var linkEnter = link.enter()
      .insert('path', "g")
      .attr("class", "link")
      .attr("stroke", "rgb(65, 136, 229)")
      .attr("stroke-width", "1px")

      .attr("d", function(d) {
        return "M" + project(source, source.x0, source.y0)
          + "L" + project(source, source.x0, source.y0);
      });

    var linkUpdate = linkEnter.merge(link);

    // Now animate the links

    linkUpdate.transition()
      .duration(duration)
      .attr("d", function(d) {
        return "M" + project(d, d.x, d.y)
          + "L" + project(d.parent, d.parent.x, d.parent.y);
      });

    // Remove any exiting links
    var linkExit = link.exit()
      .transition()
      .duration(duration)
      .attr("d", function(d) {
        return "M" + project(source, source.x, source.y)
          + "L" + project(source, source.x, source.y);
      })
      .remove();

    // Store the old positions for transition.
    nodes.forEach(function(d) {
      d.x0 = d.x;
      d.y0 = d.y;
    });

  }

  function project(d, x, y) {
    // Calculate angle, and adjust radius so that links are not too long.
    // Start playing with radius and cluster_size.
    var angle = (x - (cluster_size / 4)) / (cluster_size / 2) * Math.PI, radius = y * 0.5;
    var cors = [radius * Math.cos(angle), radius * Math.sin(angle)];
    return cors;
  }

  function collapse(d) {
    if(d.children) {
      d._children = d.children;
      d._children.forEach(collapse);
      d.children = null;
    }
  }

  // We use this function, so that all nodes won't be drawn at same time.
  // Play around with this and check it changes the output
  // If you increase the "value", animation will be slower

  function duration(d) {
    var value = 300 + (d.id * 5);
    // var value = 500+(d.id*5);
    // var value = 1500+(d.id*5);

    return value;
  }

  

  
}

这是与现有节点发生冲突的图像,也是 svg 之外的图像

4

0 回答 0