title: Best way to fit variably-sized text into a semi-circle in d3.js?
body: <p>I am currently working on a visualization in d3.js with the goal to visualize data similarity. I wish to compare my data within circles by creating two semi-circles for each node and putting the comparison data within these semicircles. My data consists of strings (each semicircle receives a single sentence).</p>
  
  <p>My current approach is as follows: <br>
  First, I create my necessary node data using the pack-layout.</p>
  
  <pre><code>var bubble = d3.pack().size([SVG_WIDTH,SVG_HEIGHT]).padding(CIRCLE_PADDING),
      root = d3.hierarchy({children: COMPARISON_DATA}).sum(function(d){  return d.children ? 0 : d[2]});
  
  var nodeData = bubble(root).children;
  </code></pre>
  
  <p>d[2] is the maximum string length of the two sentences that are being put into the semicircles and thus decides the radius of the circles. </p>
  
  <p>Next, I iterate over each node and create the corresponding semicircles. I have removed all the code-parts which are irrelevant to my question.</p>
  
  <pre><code> nodeData.forEach(function (data, index) {
      //upperCircleGroup simply adds a small y-translate, so that the semicircles have a margin 
      var gUpper = upperCircleGroup.append("g");
      var gLower = lowerCircleGroup.append("g");
  
  
      var lowerCircle = gLower.append('path')
          .attr('d', d3.arc()({
              innerRadius: 0,
              outerRadius: data.r,
              startAngle: Math.PI / 2,
              endAngle: 3 / 2 * Math.PI
          }))
          .attr('transform', `translate(${data.x},${data.y})`)
  
  
        var upperCircle = gUpper.append('path')
          .attr('d', d3.arc()({
              innerRadius: 0,
              outerRadius: data.r,
              startAngle: 1 / 2 * Math.PI,
              endAngle: - 1 / 2 * Math.PI
          }))
          .attr('transform', `translate(${data.x},${data.y})`)
  
      var upperText = gUpper
          .append("foreignObject")
          .attr("width", () =&gt; {return data.r*Math.sqrt(2)})
          .attr("height", () =&gt; {return data.r*(Math.sqrt(2)/2)})
          .attr('transform', `translate(${data.x - (data.r / Math.sqrt(2))},${data.y - (data.r/Math.sqrt(2)) })`)
          .text(() =&gt; {return data.data[0]})
  
      var lowerText = gLower
          .append("foreignObject")
          .attr("width", () =&gt; {return data.r*Math.sqrt(2)})
          .attr("height", () =&gt; {return data.r*(Math.sqrt(2)/2)})
          .attr('transform', `translate(${data.x - (data.r / Math.sqrt(2))},${data.y  })`)
          .text(() =&gt; {return data.data[1]})
  });
  </code></pre>
  
  <p>As you can see, I draw my semicircles using d3's arc. Now this is where my question arises. I've had trouble putting my textual content inside the arc, so after searching for a while I chose this solution to put a div inside my semicircles which then receives the text. The sqrt(2) operations are used to fit the square into the semicircle. </p>
  
  <p>My problem with this solution is, that at times, the sentence simply won't fit into the div and some content is lost. Is there a way to calculate the font-size of a string necessary, so that it fits the div of a given size? If this were possible, I could simply calculate the appropriate font-size and add a zoom option to the visualization. Also, if there are better ways to achieve what I am trying to do I would also be happy to get some feedback from you guys as I am a complete beginner when it comes to using d3.  </p>