Francesco Binucci
Francesco Binucci

Reputation: 71

How to place a text over a path d3.js

I've this problem with d3.js: I want to put a text over an arc. Now I'm using a textPath and the effect is this:

enter image description here

Is there a way to rotate the textPath? I want to obtain an effect like this:

enter image description here

Here's my code:

       path.attr("d",d3.arc()
      .innerRadius(5)
      .outerRadius(55)
      .startAngle(Math.PI/2+angle-10 * (Math.PI / 180)) //converting from degs to radians
      .endAngle(Math.PI/2+angle+10*(Math.PI/180)))
      .attr("transform", function(d){return "translate("+d.x+","+d.y+") rotate("+nodesMap.get(node.id).degPathRotate+")"; })
      .attr("fill", function(d) { return "red"; })  
      .attr("opacity", 0.8)
      

    invisibleMap.get(node.id).angle = angle;
          
 vis.append("text")
 .append("textPath") //append a textPath to the text element
 .attr("xlink:href", "#"+'p'+node.id) //place the ID of the path here
 .text((nodesMap.get(node.id).totRels-nodesMap.get(node.id).shownRels))

Upvotes: 2

Views: 404

Answers (1)

Mark
Mark

Reputation: 108537

I wouldn't use a textPath for this. Instead, I'd just place the text explicitly using a little trigonometry:

<!DOCTYPE html>

<html>
  <head>
    <script src="https://d3js.org/d3.v6.min.js"></script>
    <style>
      text {
        font-family: arial;
        font-weight: bold;
      }
      </style>
  </head>

  <body>
    <svg width="200" height="200"></svg>
    <script>

      var vis = d3.select('svg'),
          path = vis.append('path'),
          angle = 330,
          xPos = 100,
          yPos = 100,
          innerR = 5,
          outerR = 55;

      path
        .attr('id', 'sp')
        .attr(
          'd',
          d3
            .arc()
            .innerRadius(innerR)
            .outerRadius(outerR)
            .startAngle(Math.PI / 2 + angle - 10 * (Math.PI / 180)) //converting from degs to radians
            .endAngle(Math.PI / 2 + angle + 10 * (Math.PI / 180))
        )
        .attr('transform', function (d) {
          return (
            'translate(' +
            xPos +
            ',' +
            yPos +
            ') rotate(' +
            30 +
            ')'
          );
        })
        .attr('fill', function (d) {
          return 'red';
        })
        .attr('opacity', 0.8);

      vis
        .append('text')
        .text(20)
        //.append('textPath') //append a textPath to the text element
        //.attr('xlink:href', '#' + 'sp') //place the ID of the path here
        .attr("transform", function(){
          let l = outerR - innerR,
              x = (l * Math.cos(angle)) + xPos,
              y = (l * Math.sin(angle)) + yPos,
              bbox = this.getBBox();
          return "translate(" + x + "," + (y - bbox.height) + ")";
        })
    </script>
  </body>
</html>

Upvotes: 2

Related Questions