JustThatGuy93
JustThatGuy93

Reputation: 119

Add text over D3 node in React

So I have a JSON file called scratch that holds nodes and links...

{
  "nodes": [
    {
      "name": "Guardians of the Galaxy",
      "id": "1"
    },
    {
      "name": "Chris Pratt"
    },
    {
      "name": "Vin Diesel"
    }
  ],
  "links": [
    {
      "source": "Guardians of the Galaxy",
      "target": "Chris Pratt"
    },
    {
      "source": "Guardians of the Galaxy",
      "target": "Vin Diesel"
    }
  ]
}

And I'm trying to have the name of each node hover over the node when it's loaded. The text is also extremely large. Here is how I'm making the nodes

         const nodes_data = data['nodes'];

         let simulation = d3.forceSimulation()
              .nodes(nodes_data);

         simulation
             .force("charge_force", d3.forceManyBody())
             .force("center_force", d3.forceCenter(width / 2, height / 2));

         let node = svg.append("g")
         .attr("class", "nodes")
         .selectAll("circle")
         .data(nodes_data)
         .enter()
         .append("circle")
         .attr("r", 5)
         .attr("fill", "red");

         node.append("text")
            node.attr('transform', d => `translate(${d.name})`);

         simulation.on("tick", tickActions);

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

Note: I now know that the text is stuck in the top left because of the .attr("x/y"...), I just don't know how to get it smaller and over the nodes.


            let text = svg.append("g")
                .attr("class", "nodes")
                .selectAll("text")
                .data(nodes_data)
                .enter()
                .append("text")
                .attr("x", function(d) { return d.x })
                .attr("y", function(d) { return d.y })
                .text(function(d) { return d.name });

Upvotes: 1

Views: 1175

Answers (1)

Michael Rovinsky
Michael Rovinsky

Reputation: 7210

To ensure node labels are always above nodes, first create separate layers for both and make sure the label layer is added after the nodes' one. To make labels smaller, just set font-size:

const nodetLayer = svg.append('g');
const textLayer = svg.append('g');
...
const texts = textLayer.selectAll('text')
  .data(nodes_data)
  .enter()
  .append('text')
  .attr('font-size', `${your-font-size}px`)
...
const nodes = nodelayer.selectAll('circle')
  .data(nodes_data)
  .enter()
  .append('circle')
 

Alternatively, you can create a <g> element per node and append a <circle> and a <text> to it.

Upvotes: 1

Related Questions