D3 4.0带有定向边和标签的图形 [英] D3 4.0 Graph with directed edges and labels

查看:400
本文介绍了D3 4.0带有定向边和标签的图形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用d3(v4.0)创建一个具有节点的边和标签的图,如下所示: http://jsfiddle.net/chrisJamesC/HgHqy/ ,但带有更新版本的D3。

I am trying to create a graph with d3 (v4.0) that has directed edges and labels for the nodes, something like this: http://jsfiddle.net/chrisJamesC/HgHqy/ but with a newer version of D3.

这就是我所拥有的远: https://jsfiddle.net/4nu57pgn/1/ ,但我似乎无法数字了解如何告诉D3使边缘看起来直观(带箭头)或显示节点ID。

This is what I have so far: https://jsfiddle.net/4nu57pgn/1/ but I can't seem to figure out how to tell D3 to make the edges appear visually directed (with arrows) or to have the node IDs displayed.

var svg = d3.select("svg");
var width = svg.attr("width");
var height = svg.attr("height");
svg = svg.call(d3.zoom().on("zoom", zoomed)).append("g");
var color = d3.scaleOrdinal(d3.schemeCategory10);

var simulation = d3.forceSimulation()
    .force("link", d3.forceLink().id(function(d) { return d.id; }))
    .force("charge", d3.forceManyBody())
    .force("center", d3.forceCenter(width / 2, height / 2));

function createGraph (error, graph) {
  if (error) throw error;

  var link = svg.append("g")
      .attr("class", "links")
    .selectAll("line")
    .data(graph.links)
    .enter().append("line")
      .attr("stroke", function(d) { return color(d.type); });


  var node = svg.append("g")
      .attr("class", "nodes")
    .selectAll("circle")
    .data(graph.nodes)
    .enter().append("circle")
      .attr("r", 10)
      .attr("fill", function(d) { if (d.root == "true") return color(d.root); return color(d.type); })
      .call(d3.drag()
          .on("start", dragstarted)
          .on("drag", dragged)
          .on("end", dragended));

  node.on("click",function(d){
    console.log("clicked", d.id);
  });

  node.append("title")
      .text(function(d) { return d.id; });

  simulation
      .nodes(graph.nodes)
      .on("tick", ticked);

  simulation.force("link")
      .links(graph.links);

  function ticked() {
    link
        .attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });

    node
        .attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
  }
}

function dragstarted(d) {
  if (!d3.event.active) simulation.alphaTarget(0.3).restart();
  d.fx = d.x;
  d.fy = d.y;
}

function dragged(d) {
  d.fx = d3.event.x;
  d.fy = d3.event.y;
}

function dragended(d) {
  if (!d3.event.active) simulation.alphaTarget(0);
  d.fx = null;
  d.fy = null;
}

function zoomed() {
  svg.attr("transform", "translate(" + d3.event.transform.x + "," + d3.event.transform.y + ")" + " scale(" + d3.event.transform.k + ")");
}

我是D3新手,希望有任何帮助指出我正确的方向。

I am new to D3 and would appreciate any help pointing me in the correct direction.

推荐答案

箭头



你需要使用SVG定义一个标记。只需稍作修改即可更新d3 v3代码,以便在v4中执行此操作。您提供的示例设置了三个箭头定义(每种类型的关系都有一个),但要创建一个可以使用的定义:

Arrows

To add arrows at the end of the line you need to define a marker using SVG. Only slight modifications are required to update the d3 v3 code to do this with v4. The example you provided sets up three arrow definitions (one for each type of relationship) but to create a single one you can use this:

svg.append("defs").append("marker")
    .attr("id", "arrow")
    .attr("viewBox", "0 -5 10 10")
    .attr("refX", 20)
    .attr("refY", 0)
    .attr("markerWidth", 8)
    .attr("markerHeight", 8)
    .attr("orient", "auto")
  .append("svg:path")
    .attr("d", "M0,-5L10,0L0,5");

markerWidth markerHeight refX refY 是重要的,它决定了标记的位置 - 不幸的是,我不知道它们是如何与 viewBox 或圆弧半径相互作用的,所以这些是通过试错法选择的。

The values of markerWidth, markerHeight, refX, refY are significant and determine the placement of the markers - unfortunately I don't know how they interplay with the viewBox or the circle radius so these were selected by trial and error.

不需要将标记捕获为变量,因为它将使用URL说明符引用,如下所示:

No need to capture the marker as a variable because it will be referred to using a URL specifier as follows:

  var link = svg.append("g")
      .attr("class", "links")
    .selectAll("line")
      .data(graph.links)
    .enter().append("line")
      .attr("stroke", function(d) { return color(d.type); })
      .attr("marker-end", "url(#arrow)");



标签



v3代码将起作用。文本标签需要单独附加到SVG中,而不是作为节点的子节点,并在打勾的函数中独立转换。

设置标签:

To set up the labels:

var text = svg.append("g").attr("class", "labels").selectAll("g")
    .data(graph.nodes)
  .enter().append("g");

text.append("text")
    .attr("x", 14)
    .attr("y", ".31em")
    .style("font-family", "sans-serif")
    .style("font-size", "0.7em")
    .text(function(d) { return d.id; });

然后在力仿真滴答时将它们翻译到正确的位置:

And then to translate them to the right location when the force simulation ticks:

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

水平偏移量由设置标签时的 x 的值定义(本例中为14)。

The horizontal offset is defined by the value of x when setting up the labels (14 in this case).

请参阅这个小提琴为完整的例子。

这篇关于D3 4.0带有定向边和标签的图形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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