箭头不接触树布局中d3.js中的节点 [英] Arrows are not touching to nodes in d3.js in tree layout

查看:140
本文介绍了箭头不接触树布局中d3.js中的节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的d3树有超过500个节点(一个根和500/1000子节点到它在第二级)。箭头看起来完美多达50个子节点,但比左侧和右侧节点多,在节点和路径顶部显示的箭头对角线相交节点边。
如何解决这个问题,这样箭头应该触摸节点路径相交节点?使用的节点是矩形如在此问题中给出

I am using d3 tree with more than 500 nodes(one root and 500/1000 child nodes to it in 2nd level). Arrows looks perfect up-to 50 child nodes but more than that on left and right side nodes, arrows shown at top of node and path are intersects node edge diagonally. how to resolve this issue in such way that arrow should touch node where path intersect node?Nodes used are rectangular as given in this question Arrows are not touching to nodes in d3.js

推荐答案

好,这里是您的解决方案。这就是我所说的回退方法。这是我在此问题中使用的相同方法。它的工作原理是拟合路径,然后减去你的方形加上标记头的半径。

All right, all right here's your solution. This is what I call the "back-off" approach. It's the same approach I used in this question. It works by fitting the path and then subtracting off of it the "radius" of your square plus marker head.

几个事情,你只需要附加标记def一次,它可以用于所有的行。第二,我切换了路径,从顶部向下绘制,你让他们画出我会向后 - 从孩子到父母。

Couple things first, you only need to append the "marker" def once, it can be used on all the lines. Second, I switched the paths to draw top down, you had them drawing what I would all backwards - from child to parent. This requires additional rotation of the head.

以下是代码:

var width = 500;
var height = 500;
var nodeWidth = 40;
var nodeHeight = 40;
var circleRadius = 5;
var diagramLayout;
var graphData = {
  "nodes": [{
    "uid": "Term20",
    "name": "Term20",
    "image": "images/Term.png"
  }, {
    "uid": "glossforArrow",
    "name": "glossforArrow",
    "image": "images/Glossary.png"
  }, {
    "uid": "Term43",
    "name": "Term43",
    "image": "images/Term.png"
  }, {
    "uid": "Term1",
    "name": "Term43",
    "image": "images/Term.png"
  }, {
    "uid": "Term2",
    "name": "Term43",
    "image": "images/Term.png"
  }],
  "links": [{
    "source": "glossforArrow",
    "target": "Term20",
    "direction": "output",
    "label": "Owned Terms"
  }, {
    "source": "glossforArrow",
    "target": "Term43",
    "direction": "output",
    "label": "Owned Terms"
  }, {
    "source": "glossforArrow",
    "target": "Term1",
    "direction": "output",
    "label": "Owned Terms"
  }, {
    "source": "glossforArrow",
    "target": "Term3",
    "direction": "output",
    "label": "Owned Terms"
  }, {
    "source": "glossforArrow",
    "target": "Term4",
    "direction": "output",
    "label": "Owned Terms"
  }, {
    "source": "glossforArrow",
    "target": "Term5",
    "direction": "output",
    "label": "Owned Terms"
  }, {
    "source": "glossforArrow",
    "target": "Term6",
    "direction": "output",
    "label": "Owned Terms"
  }, {
    "source": "glossforArrow",
    "target": "Term7",
    "direction": "output",
    "label": "Owned Terms"
  }, {
    "source": "glossforArrow",
    "target": "Term8",
    "direction": "output",
    "label": "Owned Terms"
  }, {
    "source": "glossforArrow",
    "target": "Term9",
    "direction": "output",
    "label": "Owned Terms"
  }, {
    "source": "glossforArrow",
    "target": "Term2",
    "direction": "output",
    "label": "Owned Terms"
  }]
};

treeInitialize(graphData)


function treeInitialize(graphData) {

  diagramLayout = d3.select("#diagramLayout")
    .attr("id", "diagramLayout") //set id
    .attr("width", width) //set width
    .attr("height", height) //set height
    .append("g")
    .attr("transform", "translate(" + 20 + "," + 20 + ")")

  markerRefx = 40;

  var data2 = graphData.links.filter(function(l) {
    if (l.target == undefined && l.source == undefined) {
      return false;
    } else {
      return true;
    }
  });
  data2.push(JSON.parse('{"target":"glossforArrow","source":""}'))

  var treeData = d3.stratify().id(function(d) {
    return d.target;
  }).parentId(function(d) {
    return d.source;
  })(data2)

  nodes = d3.hierarchy(treeData, function(d) {
    return d.children;
  });

  var levelWidth = [1];
  var childCount = function(level, n) {

    if (n.children && n.children.length > 0) {
      if (levelWidth.length <= level + 1) levelWidth.push(0);

      levelWidth[level + 1] += n.children.length;
      n.children.forEach(function(d) {
        childCount(level + 1, d);
      });
    }
  };
  childCount(0, nodes);
  newHeight = d3.max(levelWidth) * 100;
  var tree = d3.tree().size([height, width])

  tree.size([newHeight, height / 2]);

  tree.separation(function(a, b) {
    return a.parent == b.parent ? 50 : 100;
  });
  nodes = tree(nodes);
  treeLayout(nodes);

  function treeLayout(nodes) {

    var node = diagramLayout.selectAll(".node");
    node = node.data(nodes.descendants());

    var link = diagramLayout.selectAll(".link")
      .data(nodes.descendants().slice(1))
      .enter().append("path")
      .attr("class", "link")
      .attr("fill", "none")
      .attr("stroke", "#000")
      .attr("stroke-width", "1px")
      .attr("stroke-opacity", "0.3")
      .attr("d", function(d) {
        return connector(d.parent, d);
      })

    //nodes.descendants().slice(1).forEach(function(d) { 

    var mark = diagramLayout.append("svg:defs").selectAll("marker") //
      .data(["start"]) // Different link/path types can be defined here
      .enter().append("svg:marker") // This section adds in the arrows
      .attr("id", String)
      .attr("viewBox", "0 -5 10 10")
      .attr("refX", 0)
      .attr("refY", 0)
      .attr("markerWidth", 5)
      .attr("markerHeight", 5)
      .attr("orient", "auto")
      .attr("stroke", "#000")
      .attr("fill", "#000")
      .append("svg:path")
      .attr("d", "M0,-5L10,0L0,5")
      .style("stroke-width", "0.3px")
      //.attr("transform","rotate(180,5, 0)");

    //	});	

    link.attr("marker-end", "url(#start)")
      .each(function(d, i, j) {

        var self = d3.select(this),
          t = this.getTotalLength(),
          p = this.getPointAtLength(t - 25);

        self.attr("d", connector(d.parent, p));
      })



    var nodeEnter = node.enter().append("g")
      .attr("class", "node")
      .attr("height", nodeHeight)
      .attr("width", nodeWidth)
    nodeEnter.attr("transform", function(d) {
      return "translate(" + project(d.x, d.y) + ")";
    })


    var nodeIcon = nodeEnter.append("rect")
      .attr("class", "rect")
      .attr("x", -20)
      .attr("y", -20)
      .attr("rx", 10)
      .attr("width", 40)
      .attr("height", 40)
      .attr("stroke-width", function(d) {
        return Math.sqrt(2);
      })
      .attr("stroke-opacity", "0.3")
      .attr("stroke", "#000")
      .attr("fill", "none")


    //wrap(nodeText, 8)	
  }

}

function connector(from, to) {
  return "M" + project(from.x, from.y) + "C" + project(from.x, (from.y + to.y) / 2) + " " + project(to.x, (from.y + to.y) / 2) + " " + project(to.x, to.y);
}

function project(x, y) {

  return [x, y];
}

.node {
  stroke: #fff;
  stroke-width: 1.5px;
}
.link {
  stroke: #000;
  stroke-opacity: .6;
}

<script src="https://d3js.org/d3.v4.min.js"></script>
<div id="mainScreen" style="height:100%;width:100%;position:absolute;">
  <svg id="diagramLayout" style="height:100%;width:100%;position:absolute;">
  </svg>

</div>

这篇关于箭头不接触树布局中d3.js中的节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆