score:-1

Just add this line:

.attr("text-anchor", "middle")

to the code after the line:

node.append("svg:text")

it should look like this:

node.append("svg:text")
.attr("text-anchor", "middle")
......

score:5

I am using an arch as a link between nodes with a label text placed in the middle. Here is a code snippet:

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

    var force = d3.layout.force()
     .gravity(.05)
     .distance(120)
     .charge(-100)
     .size([600, 400]);
    var nodes = force.nodes(), links = force.links();

    // make an arch between nodes and a text label in the middle
    var link = vis.selectAll("path.link").data(links, function(d) {
       return d.source.node_id + "-" + d.target.node_id; });
    link.enter().append("path").attr("class", "link");

    var linktext = vis.selectAll("g.linklabelholder").data(links);
    linktext.enter().append("g").attr("class", "linklabelholder")
     .append("text")
     .attr("class", "linklabel")
     .attr("dx", 1)
     .attr("dy", ".35em")
     .attr("text-anchor", "middle")
     .text(function(d) { return "my label" });

    // add your code for nodes  ....

    force.on("tick", tick); force.start();

    function tick () {   
     // curve
     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;
     });    
     // link label
     linktext.attr("transform", function(d) {
      return "translate(" + (d.source.x + d.target.x) / 2 + "," 
      + (d.source.y + d.target.y) / 2 + ")"; });
     // nodes 
    node.attr("transform", function(d) {
        return "translate(" + d.x + "," + d.y + ")"; });
    }

score:12

Created JS fiddle example for showing labels over links in D3 Forced layout chart

See working demo in JS Fiddle: http://jsfiddle.net/bc4um7pc/

Give Id's to your path like below

var path = svg.append("svg:g").selectAll("path")
    .data(force.links())
  .enter().append("svg:path")
    .attr("class", function(d) { return "link " + d.type; })
    .attr("id",function(d,i) { return "linkId_" + i; })
    .attr("marker-end", function(d) { return "url(#" + d.type + ")"; });

Use SVG textPath element for associating labels with above links by specifying its 'xlink:href' attribute to point to its respective link/path.

 var linktext = svg.append("svg:g").selectAll("g.linklabelholder").data(force.links());
     linktext.enter().append("g").attr("class", "linklabelholder")
     .append("text")
     .attr("class", "linklabel")
     .style("font-size", "13px")
     .attr("x", "50")
     .attr("y", "-20")
     .attr("text-anchor", "start")
     .style("fill","#000")
     .append("textPath")
    .attr("xlink:href",function(d,i) { return "#linkId_" + i;})
     .text(function(d) { 
         return "my text"; //Can be dynamic via d object 
     });

score:17

Have you experimented with creating text elements separately in a standalone (simpler) example? It should give you a better feeling for how the different attributes control positioning.

For vertical alignment, use the "dy" attribute:

  • by default, the baseline of the text is at the origin (bottom-aligned)
  • a dy of .35em centers the text vertically
  • a dy of .72em places the topline of the text at the origin (top-aligned)

Using em units is nice because it will scale automatically based on the font size. If you don't specify units (such as -20 in your code), it defaults to pixels.

For horizontal alignment, use the "text-anchor" attribute:

  • the default is "start" (left-aligned for left-to-right languages)
  • "middle"
  • "end"

There's also the "dx" attribute, which is tempting to use for padding. However, I wouldn't recommend it because there is a bug in Firefox and Opera that cause it to not work as expected in conjunction with text-anchor middle or end.

score:18

enter image description here

Use a smaller example outside of D3 to see how the SVG stuff works. Then just rebuild this structure using D3 and your custom data.

<html>
    <body>

<svg width="600px" height="400px">

    <defs>
        <!-- DEFINE AN ARROW THAT WE CAN PLACE AT THE END OF EDGES. -->
        <!-- USE REFX TO MOVE THE ARROW'S TIP TO THE END OF THE PATH. -->
        <marker
            orient="auto"
            markerHeight="12"
            markerWidth="12"
            refY="0"
            refX="9"
            viewBox="0 -5 10 10"
            id="ARROW_ID"
            style="fill: red; fill-opacity: 0.5;">

            <path d="M0, -5L10, 0L0, 5"></path>

        </marker>
    </defs>

    <!-- DEFINE A PATH. SET ITS END MARKER TO THE ARROW'S ID. -->
    <!-- SET FILL NONE TO DRAW A LINE INSTEAD OF A SHAPE. -->
    <path
        d="M100,100 A300,250 0 0,1 500,300"
        style="fill:none; stroke:grey; stroke-width:2px;"
        id="PATH_ID"
        marker-end="url(#ARROW_ID)" />

    <!-- DEFINE A TEXT ELEMENT AND SET FONT PROPERTIES. -->
    <!-- USE DY TO MOVE TEXT ABOVE THE PATH. -->
    <text
        style="text-anchor:middle; font: 16px sans-serif;"
        dy="-12">

        <!-- DEFINE A TEXT PATH FOLLOWING THE PATH DEFINED ABOVE. -->
        <!-- USE STARTOFFSET TO CENTER TEXT. -->
        <textPath
            xlink:href="#PATH_ID"
            startOffset="50%">Centered edge label</textPath>
    </text>

</svg>

    </body>
</html>

Related Query

More Query from same tag