hasi90
hasi90

Reputation: 84

Get width of text node in d3 inside .attrs method

I have added some text nodes using d3 as below.

svg.selectAll('text.label')
    .data(studentTable, d => d.name)
    .enter()
    .append('text')
    .attrs({
      class: 'label',
      x: d => x(d.value),
      y: d => y(d.rank),
    })

Now in transition i need to access the width of the currently selected text node and set the x position according to the width. (See the comments of below code snippet).

svg.selectAll('.label').data(studentTable, d => d.name)
        .transition()
        .duration(tickDuration)
        .ease(d3.easeLinear)
        .attrs({
          x: d => x(d.value), // Here i need to get the width of current text node to set x position
          y: d => y(d.rank)
        });

Any convenient way to do this ? Thanks

Upvotes: 1

Views: 636

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102194

The method for getting the text length is getComputedTextLength(), which you have to use with the node. To get the text node inside the arrow function, use the third and second arguments combined. So:

.attrs({
    x: (d, i, n) => n[i].getComputedTextLength() + whatever, 
    y: d => y(d.rank)
});

Here is a demo using your code, the red line shows the end of the text:

const svg = d3.select("svg");
svg.selectAll('text.label')
  .data([{
    value: 100,
    rank: 50
  }])
  .enter()
  .append('text')
  .attrs({
    class: 'label',
    x: d => d.value,
    y: d => d.rank,
  })
  .text("Lorem ipsum dolor sit amet");
  
svg.append("line")
  .attr("x1", 100 + svg.select(".label").node().getComputedTextLength())
  .attr("x2", 100 + svg.select(".label").node().getComputedTextLength())
  .attr("y1", 0)
  .attr("y2", 100)
  .style("stroke", "red");

svg.selectAll('.label')
  .data([{
    value: 100,
    rank: 50
  }])
  .transition()
  .delay(1000)
  .duration(1000)
  .ease(d3.easeLinear)
  .attrs({
    x: (d, i, n) => d.value + n[i].getComputedTextLength(),
    y: d => d.rank
  });
<svg width="500" height="100"></svg>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>

Upvotes: 3

Related Questions