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",...