JSFiddle - React, Tailwind, and code Playground
CSS
rect.box {
fill:none;
stroke:royalblue;
stroke-width:5;
shape-rendering: crispEdges;
}
g.bubbles circle {
fill:rgba(255,0,64,0.5);
stroke:rgb(255,0,64);
stroke-width:3;
}
g.bubbles text {
fill:royalblue;
font-family:sans-serif;
text-anchor:middle;
alignment-baseline:middle;
opacity:0;
pointer-events:all;
transition:1s;
}
g.bubbles text:hover {
opacity:1;
}
JavaScript
(function() {
//D3 program to fit circles of different sizes
//in a rectangle of fixed aspect ratio
//as tightly as reasonable.
//
//By Amelia Bellamy-Royds, in response to
//http://stackoverflow.com/questions/13339615/packing-different-sized-circles-into-rectangle-d3-js
//Based on Mike Bostock's
//"http://bl.ocks.org/mbostock/7882658" example:
//http://bl.ocks.org/mbostock/7882658
//parameters//
var N = 25; //number of nodes
var sortOrder = -1;
//>0 for ascending, <0 for descending, 0 for no sort
//create data array//
var data = [], i = N;
var randNorm = d3.random.normal(1,0.6);
while(i--) data.push({
"size": Math.max(randNorm(), 0.1) });
//circle area will be proportional to size
var dataMax = d3.max(data, function(d){return d.size;});
var totalSize = d3.sum(data, function(d){return d.size;});
//________________//
//Set up SVG and rectangle//
var svg = d3.select("svg");
var digits = /(\d*)/;
var margin = 50; //space in pixels from edges of SVG
var padding = 4; //space in pixels between circles
var svgStyles = window.getComputedStyle(svg.node());
var width = parseFloat(svgStyles["width"]) - 2*margin;
var height = parseFloat(svgStyles["height"]) - 2*margin;
var usableArea = Math.PI*
Math.pow( Math.min(width,height)/2 ,2)*0.667;
var scaleFactor = Math.sqrt(usableArea)/
Math.sqrt(totalSize)/Math.PI;
var rScale = d3.scale.sqrt()
//make radius proportional to square root of data r
.domain([0, dataMax]) //data range
.range([0, Math.sqrt(dataMax)*scaleFactor]);
//The rScale range will be adjusted as necessary
//during packing.
//The initial value is based on scaling such that the total
//area of the circles is 2/3 the area of the largest circle
//you can draw within the box.
//*
console.log("Dimensions: ", [height, width]);
console.log("area", width*height);
console.log("Usable area: ", usableArea);
...