D3 基于名称而不是索引链接节点 [英] D3 Linking nodes based on names rather than index

查看:27
本文介绍了D3 基于名称而不是索引链接节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试根据 Id 而不是此 codepen<中的索引链接节点/a>,我不知道该怎么做.

I am trying to link the nodes based on Id rather than the index in this codepen, I am not able to figure out how to do it.

以下工作:

var links = [{ source:  0, target: 1 }];

但是如果我根据名称创建链接,它不会创建任何链接.

But if I create a link based on names, it does not create any link.

var links = [{ source: "FH" , target: "TP"  }];

推荐答案

D3v3 强制布局不支持链接中的命名节点.如果您想在不需要任何额外工作的情况下使用它们,我建议使用 d3v4 或 v5.

A D3v3 force layout doesn't support named nodes in the links. I'd suggest d3v4 or v5 if you want to use them without requiring any extra work.

但是,与 REEE 的回答一样,您可以通过更改代码并保留 v3 来达到相同的效果.我没有更改刻度,而是在启动数组之前更改 link 数组:

But, as with REEE's answer, you can achieve the same effect by altering your code and keeping v3. Rather than alter the tick, I'm altering the link array prior to initiating the array:

var obj = {}
nodes.forEach(function(d,i){
  obj[d.id] = i;             // create an object to look up a node's index by id
})

links.forEach(function(d) {
  d.source = obj[d.source];  // look up the index of source
  d.target = obj[d.target];  // look up the index of target
})

这是一个分叉的 plunkr,或者下面的一个片段(我已经将您的节点数组移动到它自己的变量中 - 是的,它被称为节点,稍后会被覆盖):

Here's a forked plunkr, or a snippet below (I've moved your node array into its own variable - yes, it's called nodes and gets overwritten later):

var width = 500,
  height = 200;

var fill = d3.scale.category20();
var links = [{ source:  "FH", target: "TP" }];
var nodes = [
    { id: "FH", x: 100, y: 110 },
    { id: "TP", x: 200, y: 110 },
    { id: "GW", x: 200, y: 110 },
    { id: "DB", x: 100, y: 110 }
  ]

var obj = {}
nodes.forEach(function(d,i){
  obj[d.id] = i;
})

links.forEach(function(d) {
  d.source = obj[d.source];
  d.target = obj[d.target];
})

var force = d3.layout
  .force()
  .size([width, height])
  .nodes(nodes)
  .links(links)
  .linkDistance(150)
  .charge(-500)
  .on("tick", tick);

var svg = d3
  .select("body")
  .append("svg")
  .attr("width", width)
  .attr("height", height);

var arrows = svg
  .append("svg:defs")
  .selectAll("marker")
  .data(["arrow"])
  .enter()
  .append("marker")
  .attr("id", String)
  .attr("viewBox", "0 -5 10 10")
  .attr("refX", 15)
  .attr("refY", -1.5)
  .attr("markerWidth", 6)
  .attr("markerHeight", 6)
  .attr("orient", "auto")
  .append("path")
  .attr("d", "M0,-5L10,0L0,5");

svg
  .append("rect")
  .attr("width", width)
  .attr("height", height);

var nodes = force.nodes(),
  links = force.links(),
  node = svg.selectAll(".node"),
  link = svg.selectAll(".link");

restart();





function tick() {
  link.attr("d", function(d) {
    var dx = d.target.x - d.source.x,
      dy = d.target.y - d.source.y,
      dr = Math.sqrt(dx * dx + dy * dy);
    return (
      "M" +
      d.source.x +
      "," +
      d.source.y +
      "A" +
      dr +
      "," +
      dr +
      " 0 0,1 " +
      d.target.x +
      "," +
      d.target.y
    );
  });

  node.attr("transform", function(d) {
    return "translate(" + d.x + "," + d.y + ")";
  });
}

function restart() {
  node = node.data(nodes);
  node
    .enter()
    .insert("g")
    .attr("class", "node")
    .call(force.drag);
  node
    .append("image")
    .attr("xlink:href", "https://github.com/favicon.ico")
    .attr("x", -8)
    .attr("y", -8)
    .attr("width", 16)
    .attr("height", 16);
  node
    .append("text")
    .attr("dx", 12)
    .attr("dy", ".35em")
    .text(function(d) {
      return d.id;
    });
  node.exit().remove();

  link = link.data(links);
  link
    .enter()
    .append("path")
    .attr("class", "link")
    .attr("marker-end", "url(#arrow)");
  link.exit().remove();

  force.start();
}

#nodeConsole {
  width: 80%;
  height: 1px;
  font-family: courier new;
  padding: 1px;
  border: 3px solid gray;
  margin-top: 1px;
  overflow: autao;
}

#linkedNodes {
  width: 80%;
  font-family: courier new;
  padding: 10px;
}

#srcNodes {
  width: 40%;
  font-family: courier new;
  padding: 8px;
}

#targetNodes {
  width: 40%;
  font-family: courier new;
  padding: 8px;
}

rect {
  fill: none;
  pointer-events: all;
}

.node {
  fill: #000;
}

.cursor {
  fill: none;
  stroke: brown;
  pointer-events: none;
}

.link {
  stroke: #999;
}
.node text {
  pointer-events: none;
  font: 10px sans-serif;
}

path.link {
  fill: none;
  stroke: #666;
  stroke-width: 1.5px;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

这篇关于D3 基于名称而不是索引链接节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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