d3.js - 树节点距离等于边界到边界

时间:2021-06-22 20:11:17

标签: d3.js

我希望从边界到边界的树节点距离相等,默认情况下是从中心到中心。

draw_tree()
function tree(root) {
  var width = 300
  var height = 140
  var step = 50
  var margin = {top: 0, right: 40, bottom: 0, left: 40}

  var treemap = d3.tree().size([height,200])
  var node = treemap(d3.hierarchy(root))

  var svg = d3.select("body").append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)

  var nodes = treemap(d3.hierarchy(root))
  var g = svg.selectAll("g")
  .data([nodes])
  .enter().append("g")
  .attr("class", "nodes")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var link = g.append("g")
  .attr("class", "link")
  .selectAll("path")
  .data(function(d) { return treemap(d).links(); })
  .enter().append("path")
  .attr("class", "links")
  .attr('fill','none')
  .attr('stroke','black')

  var node = g.append("g")
  .attr("class", "node")
  .selectAll("g")
  .data(function(d) { return nodes; })
  .enter().append("g")
  .attr("class", "nodes")

  node.append("rect")
    .attr('fill','none')
  
  var pos = []
  var txt = node.append("text")
  .attr("dy", ".35em")
  .attr("text-anchor", "middle")
  .attr("font-family", "sans-serif")
  .attr('font-size',12)
  .text(function(d) { 
    return d.data.type == 'hidden'?'':d.data.name; 
  })
  .each(function(d,i,n) { 
    d.width = Math.max(50, this.getComputedTextLength() + 10); 
    d.height=20
    if (d.data.type == 'hidden') {
      d.width = 0
      d.height = 0
    }
  })
  .attr("x",0);

  node.filter(function(d) { return "join" in d.data; }).insert("path", "text")
    .attr("class", "join");

  tick(svg);
  return svg;
}

function tick(svg) {
  var node = svg.selectAll(".node g")
  .attr("class", function(d) { return d.data.type; })
  .attr("transform", function(d, i) { return "translate("+ d.y + "," + d.x + ")"; })

  node.select("rect")
    .attr('stroke','black')
    .attr("ry", 0)
    .attr("rx", 0)
    .attr('x',d => -d.width/2)
    .attr("y", d => -d.height/2)
    .attr("height", 20)
    .attr("width", function(d) { return d.width; })

  var diagjoin = function link(d) {
    var sy = d.width
    var sx = 0
    var ty = 88
    var tx = d.data.join * 24
    return "M" + sy + "," + sx
      + "C" + (sy + ty) / 2 + "," + sx
      + " " + (sy + ty) / 2 + "," + tx
      + " " + ty + "," + tx;
  };

  var diagpath = function link(d) {
    var sy = d.source.y
    var sx = d.source.x
    var ty = d.target.y
    var tx = d.target.x
    return "M" + sy + "," + sx
      + "C" + (sy + ty) / 2 + "," + sx
      + " " + (sy + ty) / 2 + "," + tx
      + " " + ty + "," + tx;
  };

  const zagzag1 = (d) => {
    let from = d.source
    let to = d.target
    let dx = to.y - from.y;
    let dy = to.x - from.x;
    if (Math.abs(dx) > Math.abs(dy)) {
      let mx,my,nx,ny,sx,sy
      sx = (dx>0)?1:-1
      sy = (dy>0)?1:-1
      mx = from.y + from.width/2*sx
      my = from.x
      nx = to.y - to.width/2*sx
      ny = to.x
      dx = nx - mx;
      dy = ny - my;

      return `M ${mx},${my} l ${dx/2},0 0,${dy} ${dx/2},0 `;
    }else{//vertical
      let mx,my,nx,ny,sx,sy
      sx = (dx>0)?1:-1
      sy = (dy>0)?1:-1
      mx = from.y 
      my = from.x + from.height/2*sy
      nx = to.y
      ny = to.x - to.height/2*sy
      dx = nx - mx;
      dy = ny - my;
      return `M ${mx},${my} l 0,${dy/2} ${dx},0 0,${dy/2}`; 
    }
  };

  const zagzag = (d) => {
    let from = d.source
    let to = d.target
    let dx = to.y - from.y;
    let dy = to.x - from.x;
    if (Math.abs(dx) > Math.abs(dy)) {
      let mx,my,nx,ny,sx,sy
      sx = (dx>0)?1:-1
      sy = (dy>0)?1:-1
      mx = from.y + from.width/2*sx
      my = from.x
      nx = to.y - to.width/2*sx
      ny = to.x
      dx = nx - mx;
      dy = ny - my;

      return `M ${mx},${my} l 0,${dy} ${dx},0`;
    }else{//vertical
      let mx,my,nx,ny,sx,sy
      sx = (dx>0)?1:-1
      sy = (dy>0)?1:-1
      mx = from.y 
      my = from.x + from.height/2*sy
      nx = to.y
      ny = to.x - to.height/2*sy
      dx = nx - mx;
      dy = ny - my;
      return `M ${mx},${my} l ${dx},0 0,${dy}`; 
    }
  };

  node.select(".join")
    .attr("d",d => zagzag(d) );

  svg.selectAll(".link path")
    .attr("d", d => zagzag(d));
}

function draw_tree() {
  tree(
    {name:'AAAA',children:[
      {name: "AAAA",type:'hidden', children: [
        {name: "BBBB", children: [{name: "HHHH"}]},
        {name: "CCCC", children: [{name: "IIII"}]},
        {name: "DDDD", children: [{name: "JJJJ"}]},
        {name: "EEEE", children: [{name: "KKKK"}]},
        {name: "FFFF", children: [{name: "LLLL"}]},
        {name: "GGGG", children: [{name: "MMMM"}]},
      ]}
    ]}
  );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>

0 个答案:

没有答案