# Circle Packing with d3-force

This tutorial is a variation around the general introduction to circle packing with react and d3.js. You should probably understand the concepts described there before reading here.

Instead of relying on the `pack()` function of d3.js to compute the best node positions, this example suggests to rely on the d3-force plugin to apply physical forces on each node.

A code sandbox is provided for the final result, but explanations target what's different compared to a classic circular packing based on some concepts described in the network diagram section.

## Plot and code

Here is the final plot we're trying to achieve here, together with its code:🙇‍♂️

It is a circular packing chart where all circles represent an item of the dataset.

• The circle area is proportional to the `value` property of the data item.
• All circles are close to each other but do not collide. They are also attracted by the `y=0` horizontal axis, what aligns them horizontally

To understand how this chart works, you need the concepts described in the Network diagram and Circle pack sections.

A circle packing chart made using the d3-force plugin, with bubbles being attracted by the `y=0` baseline.

## Using `d3-force`

This example is actually a variation of a network diagram, but with no links between nodes.

Some physical forces are applied to each node to compute their position through an iterative simulation:

``````d3.forceSimulation(nodes)
.force(
'collide',
)
.force('charge', d3.forceManyBody().strength(80))
.force('center', d3.forceCenter(width / 2, height / 2))
.force('charge', d3.forceY(0).strength(0.05))``````

Here is a reminder:

• collide avoids circle overlap. It uses each node radius to make sure there is no collision.
• manyBody makes sure that nodes are attracted one to each other since the `strength` in use is positive.
• forceCenter center the whole chart on the canvas.
• forceY aligns bubble on a horizontal line.

## Bubble Size

As explained in the bubble chart section, it is very important to have the bubble area being proportional to the numeric`value` of the data point.

It is a very common mistake to make the radius proportional to numeric value, which leads to a misleading visualization.

Fortunately, it is very straightforward to scale the bubble appropriately thanks to the `scaleSqrt()` function.

``````const sizeScale = scaleSqrt()
.domain([min, max])
.range([BUBBLE_MIN_SIZE, BUBBLE_MAX_SIZE]);``````

## Contact

👋 Hey, I'm Yan and I'm currently working on this project!

Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting `yan.holtz.data` with `gmail.com`. You can also subscribe to the newsletter to know when I publish more content!