JSFiddle - React, Tailwind, and code Playground

by dkline

HTML

<div id="stuffToDraw">
  <svg width="500px" height="500px"></svg>
</div>

JavaScript

function getSize() {
  var d3text = d3.select(this);
  var circ = d3.select(this.previousElementSibling); // in other cases could be parentElement or nextElementSibling
  var radius = Number(circ.attr("r"));
  var offset = Number(d3text.attr("dy"));
  var textWidth = this.getComputedTextLength(); // TODO: this could be bounding box instead
  var availWidth = chordWidth(Math.abs(offset), radius); // TODO: could adjust based on ratio of dy to radius 
  availWidth = availWidth * 0.85; // fixed 15% 'padding' for now, could be more dynamic/precise based on above TODOs
  d3text.attr("data-scale", availWidth / textWidth); // sets the data attribute, which is read in the next step
}

function chordWidth(dFromCenter, radius) {
  if (dFromCenter > radius) return Number.NaN;
  if (dFromCenter === radius) return 0;
  if (dFromCenter === 0) return radius * 2;

  // a^2 + b^2 = c^2
  var a = dFromCenter;
  var c = radius;
  var b = Math.sqrt(Math.pow(c, 2) - Math.pow(a, 2)); // 1/2 of chord length

  return b * 2;
}

function appendScaledText(parentGroup, textVal, dyShift) {
  parentGroup
    .append("text")
    .attr("dy", dyShift)
    .attr("text-anchor", "middle")
    .attr("dominant-baseline", "central")
    .attr("font-family", "sans-serif")
    .attr("fill", "white")
    .text(textVal)
    .style("font-size", "1px")
    .each(getSize)
    .style("font-size", function() {
      return d3.select(this).attr("data-scale") + "px";
    });
}

var svg = d3.select("#stuffToDraw svg");

var circRadius = 5 + (Math.random() * 95);
var xPole = (Math.random() >= 0.5) ? 1 : -1;
var yPole = (Math.random() >= 0.5) ? 1 : -1;

var tx = Math.random() * circRadius * xPole + 250;
var ty = Math.random() * circRadius * yPole + 250;
var group = svg.append("g").attr("transform", "translate(" + tx + "," + ty + ")");

var dPole = (Math.random() >= 0.5) ? 1 : -1;
var textShift = Math.random() * circRadius * 0.5 * dPole;

group.append("circle").attr("r", circRadius).attr("fill",...