Packing different sized circles into rectangle - d3.js
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.
Introduction
Packing circles of different sizes inside a rectangle is not something d3.pack() solves directly. D3's built-in pack layout arranges circles inside an enclosing circle, so for a rectangular container you normally use a force simulation with collision handling and boundary constraints.
Why a Force Simulation Works
Each circle has an x, y, and r value. A force simulation nudges circles until overlaps are resolved. On every tick, you can clamp each circle back inside the rectangular bounds.
That will not always produce a mathematically optimal packing, but it is practical, animated, and easy to adapt for interactive graphics.
Basic D3 Example
The example below creates circles with different radii and packs them into an 800 by 400 SVG area.
The collision force keeps circles from overlapping, while the clamp logic ensures each one stays inside the rectangle.
Improving the Layout
A plain center force tends to create a blob near the middle. If you want a more even fill, seed the initial positions on a grid or use several weak attractors instead of only the center.
For example, starting circles near the center can reduce settling time, while starting them on a grid can reduce early collisions. The best choice depends on whether you want a dense central cluster or a more uniformly distributed arrangement.
You can also sort circles by radius before binding data. Larger circles tend to stabilize better when the layout gives them space early.
When d3.pack() Is Still Useful
Even though d3.pack() targets circular enclosures, it can still provide reasonable initial coordinates for a force simulation. One workflow is:
- Generate a rough packed layout with
d3.pack(). - Copy those coordinates into your nodes.
- Run a rectangular force simulation to adjust them.
That hybrid approach is useful when the circles represent hierarchy and you want the force layout to preserve some of the packed structure.
Boundary Handling Matters
Without explicit boundary logic, the collision force can push circles outside the SVG area. Clamping during each tick is the simplest fix, but it can make circles stick to walls.
If you want smoother wall behavior, add custom forces that push circles away from edges before they cross the boundary. That requires more code, but the motion looks more natural than hard clamping.
Performance Considerations
Force simulations are fine for dozens or a few hundred circles, but performance drops as the number of circles grows. Large datasets may need fewer iterations, smaller collision padding, or offscreen precomputation.
If the layout is static, you can let the simulation settle once and then stop it.
That avoids continuous animation cost after the layout has stabilized.
Common Pitfalls
A common mistake is trying to use d3.pack() alone and expecting it to respect a rectangular boundary. It will not, because its geometry is based on a circle-packing model.
Another issue is forgetting that collision radius should usually include a little padding. Without it, circles can visually touch or flicker at the boundary between collisions.
Developers also sometimes clamp position only once instead of on every tick. The simulation will immediately push nodes out again unless the bounds are enforced continuously.
Summary
- '
d3.pack()does not directly pack circles into a rectangle.' - A force simulation with
forceCollide()is the usual D3 solution. - Clamp node positions on every tick to keep circles inside the rectangle.
- Seed positions and sort by size if you want a more stable layout.
- For static charts, stop the simulation after it settles.
Related reading
- Padding time-series subsequences for LSTM-RNN training
- pandas - add new column to dataframe from dictionary
- Pandas and scikit-learn KeyError .... not in index
- Pandas column of lists, create a row for each list element
- Pandas convert dataframe to array of tuples
- Pandas 'countdistinct' equivalent
- Pandas create empty DataFrame with only column names
- Pandas DataFrame column to list
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.