简体   繁体   中英

Draw text on svg path element with d3.js

I am trying to modify this force directed graph , and in particular what I'd like to do is to draw text on each graph edge. I tried the following:

  // add new links
  path.enter().append('svg:path')
    .attr('class', 'link')
    .classed('selected', function(d) { return d === selected_link; })
    .style('marker-start', function(d) { return d.left ? 'url(#start-arrow)' : ''; })
    .style('marker-end', function(d) { return d.right ? 'url(#end-arrow)' : ''; })
    .on('mousedown', function(d) {
      if(d3.event.ctrlKey) return;

      // select link
      mousedown_link = d;
      if(mousedown_link === selected_link) selected_link = null;
      else selected_link = mousedown_link;
      selected_node = null;
      restart();
    })
    .append('svg:text').attr('x', 0).attr('y', 4)
    .attr('class', 'id').text(function(d) { console.log(d.id); return d.id; })

Only the last line is my modification. I also added an id property to the link objects so the code I'm working with is not exactly what I've linked to. The log statement is printing as expected but no text or error messages appear. How can I append text right in the middle of each link ?

You will need to use the svg group <g> , that will let you append elements inside.

var new_paths = path.enter().append('g'),
    links = new_paths.append('svg:path').attr('class', 'link');

Be free to add whatever style or behaviour to links as you wish. Then, for the labels, you will append again to the group:

var labels = new_paths.append('svg:text').attr('class', 'label');

And again you can add whatever you want to labels .

When you define the force, you will need to select the links and labels, wich will be something like this:

force.on("tick", function() {
    links.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; });

    labels.attr("transform",function(d){
        return
        "translate("+
            (0.5*(d.source.x+d.target.x))+
        ","+
            (0.5*(d.source.y+d.target.y))+
        ")";
    });
});

Here is a demo fiddle http://jsfiddle.net/k2oyef30/

Update

Sorry, I didn't follow your example before. Here is your particular solution.

Change path to be defined as:

// handles to link and node element groups
var path = svg.append('svg:g').selectAll('.path'),
    circle = svg.append('svg:g').selectAll('g');

Inside function tick() { you have to select the .links or the .id

path.select('.link').attr('d', function(d) {

and manage the new element:

path.select('.id').attr("transform",function(d){
    return "translate("+
        (0.5*(d.source.x+d.target.x))+
    ","+
        (0.5*(d.source.y+d.target.y))+
    ")";
});

Inside function restart() { you have to create a <g> element, for example with class path , and append the elements into it.

// add new links
var newPaths = path.enter().append('svg:g').attr('class','path');

newPaths.append('svg:path')
    .attr('class', 'link')
    .classed('selected', function(d) { return d === selected_link; })
    .style('marker-start', function(d) { return d.left ? 'url(#start-arrow)' : ''; })
    .style('marker-end', function(d) { return d.right ? 'url(#end-arrow)' : ''; })
    .on('mousedown', function(d) {
        if(d3.event.ctrlKey) return;

        // select link
        mousedown_link = d;
        if(mousedown_link === selected_link) selected_link = null;
        else selected_link = mousedown_link;
        selected_node = null;
        restart();
    });

newPaths.append('svg:text').attr('x', 0).attr('y', 4)
    .attr('class', 'id').text(function(d) { return d.id; });

The problem with the example definition was that it already selected the <path> element making you unable to select the new <g class="path">

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM