D3 4.0 Graph with directed edges and labels

后端 未结 1 997
感情败类
感情败类 2021-01-21 09:53

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 versi

相关标签:
1条回答
  • 2021-01-21 10:32

    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");
    

    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.

    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)");
    

    Labels

    Again, slight modifications to the v3 code will work. Text labels need to be appended to the SVG separately, not as children of the nodes, and translated independently in the ticked function.

    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 + ")"; })
      }
    

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

    Together

    See this fiddle for the complete example.

    0 讨论(0)
提交回复
热议问题