user2091936
user2091936

Reputation: 556

d3js text not showing on node graph

Wondering if you can help. I have tried different stylings and different d3js examples but they all fail to show the text on the node. Any ideas this would be?

The task is quite simple really. Show the text on top of a node. I really have no idea why this is not working so your help is much appreciated.

Many thanks for your help in advance.

Below is the code, but for convenience here is the fiddle http://jsfiddle.net/rg5pmrz1/

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <title>Force Layout Example 1</title>
    <style>

.node {
    fill: #ccc;
    stroke: #fff;
    stroke-width: 2px;
}

.link {
    stroke: #777;
    stroke-width: 2px;
}

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

text {
  font: 10px sans-serif;
  pointer-events: none;
}

    </style>
</head>
<body>
    <script src='http://d3js.org/d3.v3.min.js'></script>
    <script>

// Define the dimensions of the visualization. We're using
// a size that's convenient for displaying the graphic on
// http://jsDataV.is

var width = window.innerWidth - 20,
    height = innerHeight - 20;

var color = d3.scale.category10();

var force = d3.layout.force()
    .charge(-300)
    .linkDistance(function (l) { return l.value; })
    .gravity(0.03)
    .friction(0.9)
    .size([width, height]);

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

var graph = getData();

var nodeMap = {};

graph.nodes.forEach(function(d) { 

    nodeMap[d.name] = d;
    //centering first element   
   if(d.main == true)
   {
        graph.nodes[0].x = width / 2;
        graph.nodes[0].y = height / 2;
    }

});

graph.links.forEach(function(l) {
    l.source = nodeMap[l.source];
    l.target = nodeMap[l.target];
    l.distance = l.value;
    l.size = l.value;
})

force.nodes(graph.nodes)
    .links(graph.links)
    .start();

var link = svg.selectAll(".link")
    .data(graph.links)
    .enter().append("line")
    .attr("class", "link")
    .style("stroke-width", function(d) {
        return 1 / (d.value / 1000);
    });



var node = svg.selectAll(".node")
    .data(graph.nodes)
    .enter().append("circle")
    .attr("class", "node")
    .attr("r", 30)
    .style("fill", function(d) { return color(d.group); })

    .on("mouseover", mouseover)
    .on("mouseout", mouseout)
    .call(force.drag);


node.append("title")
      .attr("dy", ".35em")
      .attr("text-anchor", "middle")
      .text(function(d) { return d.name});

node.append("text")
    .attr("x", 12)
    .attr("dy", ".35em")
    .text(function(d) { return d.name;console.log("name: " + d.name); });

force.on("tick", function() {

    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 mouseover() {
    console.log("mouse over");
  d3.select(this).transition()
      .duration(250)
      .attr("r", 60);
}

function mouseout() {
    console.log("mouse out");
  d3.select(this).transition()
      .duration(250)
      .attr("r", 30);
}

function click() {
    console.log("clicky clicky");
  d3.select(this).transition()
      .duration(250)
      .attr("r", 60);

}



function getData() {

  return {
  "nodes":[
      {"name":"John","group":1, "value": 1, "main": true},
    {"name":"Mike","group":2, "value": 2},
    {"name":"Ian","group":1, "value": 3},
    {"name":"James","group":2, "value": 4},
    {"name":"Sarah","group":2,"value": 5}
  ],
  "links":[
    {"source":"John","target":"Mike","value":100},
    {"source":"Ian","target":"John","value":200},
    {"source":"John","target":"James","value":100},
    {"source":"Sarah","target":"John","value":300},
  ] };    

}



    </script>
</body>
</html>

Upvotes: 2

Views: 1176

Answers (2)

user2091936
user2091936

Reputation: 556

This seems to reduce the flickering. Replace the var node = etc. with the following:

var node = svg.selectAll(".node")
.data(graph.connections)
.enter().append("g") //this appends the G to enable the text
.attr("class", "node")
.call(force.drag);


node.append("circle") //then we add the circle
.attr("class", "node")
.attr("r", function (d) {
    if (d.main == true)
    {
        return 45;
    }
    else
    {
        return 30;
    }
})

.style("fill", function(d) { return color(d.group); })
.on("mouseover", mouseover)
.on("mouseout", mouseout)
.call(force.drag);

Upvotes: 0

davidhwang
davidhwang

Reputation: 1511

From the answers to duplicate questions here and here, it is because:

You can't add svg text to a svg circle. You should first create an svg g object (g stands for group) for each node, and than add a circle and a text for each g element, like in this code:

jsFiddle. Note the additional code in the tick function.

var width = window.innerWidth - 20,
    height = innerHeight - 20;

var color = d3.scale.category10();

var force = d3.layout.force()
    .charge(-300)
    .linkDistance(function (l) { return l.value; })
    .gravity(0.03)
    .friction(0.9)
    .size([width, height]);

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

var graph = getData();

var nodeMap = {};

graph.nodes.forEach(function(d) { 

    nodeMap[d.name] = d;
    //centering first element   
   if(d.main == true)
   {
        graph.nodes[0].x = width / 2;
        graph.nodes[0].y = height / 2;
    }

});

graph.links.forEach(function(l) {
    l.source = nodeMap[l.source];
    l.target = nodeMap[l.target];
    l.distance = l.value;
    l.size = l.value;
})

force.nodes(graph.nodes)
    .links(graph.links)
    .start();

var link = svg.selectAll(".link")
    .data(graph.links)
    .enter().append("line")
    .attr("class", "link")
    .style("stroke-width", function(d) {
        return 1 / (d.value / 1000);
    });

var node = svg.selectAll(".node")
    .data(graph.nodes)
    .enter().append("g");

var circle = node.append("circle")
    .attr("class", "node")
    .attr("id", function (d) { return d.name; })
    .attr("r", 30)
    .style("fill", function (d) {
        return color(d.group);
    })
    .on("mouseover", mouseover)
    .on("mouseout", mouseout)
    .call(force.drag);

var label = node.append("svg:text")
    .text(function(d) { return d.name; });

force.on("tick", function() {
    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("transform", function(d) {
        console.log(d);
        return 'translate(' + [d.x, d.y] + ')'; 
    });
});

function mouseover() {
    console.log("mouse over");
  d3.select(this).transition()
      .duration(250)
      .attr("r", 60);
}

function mouseout() {
    console.log("mouse out");
  d3.select(this).transition()
      .duration(250)
      .attr("r", 30);
}

function click() {
    console.log("clicky clicky");
  d3.select(this).transition()
      .duration(250)
      .attr("r", 60);
}



function getData() {

  return {
  "nodes":[
      {"name":"John","group":1, "value": 1, "main": true},
    {"name":"Mike","group":2, "value": 2},
    {"name":"Ian","group":1, "value": 3},
    {"name":"James","group":2, "value": 4},
    {"name":"Sarah","group":2,"value": 5}
  ],
  "links":[
    {"source":"John","target":"Mike","value":100},
    {"source":"Ian","target":"John","value":200},
    {"source":"John","target":"James","value":100},
    {"source":"Sarah","target":"John","value":300},
  ] };    

}

Upvotes: 3

Related Questions