![How to Build a Bubble Chart Using d3.js?](https://magora-systems.com/storage/blog/tYzH7uc0DfjDX0gBNN8QJHIGZvTViZ5Kj3v0tzZp.webp)
How to Build a Bubble Chart Using d3.js?
![How to Build a Bubble Chart Using d3.js?](https://magora-systems.com/storage/blog/tYzH7uc0DfjDX0gBNN8QJHIGZvTViZ5Kj3v0tzZp.webp)
How it all began
It all began as it is supposed to – with a Technical Specification. It was sufficient enough to start working right away. It included a description of page business logics as a whole and information about the parameters responsible for grouping or filtering bubbles and other important details. Also they attached an example we could use to build bubbles’ logics and physics.Let’s start
Looking through the source code of an existing page seemed a bit too complicated, so we found a source with a simple description of bubbles’ physics. I’d have to say that for someone, who just started working with D3’s Force Layout concepts like friction, charge, gravity might seem complicated. Even the official site states that those names are “perhaps misleading”. And it’s true! Here’s a brief description of the parameters:friction is a parameter responsible for DOM node acceleration. For example, if the value of a parameter equals 1, acceleration will be almost instant – a node will go from A to B in a flash. If the value is between 0 and 1, node motion will take some time. In case the parameter value equals 0, a node will freeze and won’t go anywhere.
charge is a parameter defining the force of node attraction/repulsion from each other. From personal experience I can tell you, that it’s a useful parameter for simple cases, but in our situation it became a stumbling block. But this is a topic for later.
gravity is a parameter that determines the attraction/repulsion of nodes from the centre.>
I’m not going to reinvent the wheel, as the library author’s blog has many examples of using these forces. Here’s a short description:
1) To create a "force" just declare it and set sizes:
this._force = d3.layout.force();
this._force.size([width, height]);
All other parameters will be determined automatically
2) To add nodes to it you’ll need to use the “nodes” method:this._force.nodes(data);Data is an array of objects containing node parameters. An object can contain any fields, but some field names are used as initial values of the “force”. In order to make the “force” move the nodes the way we want it to, we need to determine the “tick” event handler. It reacts to every “frame” of the force and allows to calculate the next position of a node. That’s where the magic begins… We’ll talk about it later. The force can be activated with the help of “start” method:
this._force.start();Use of this method “brings our force to life”.
Processing force “frame”
As mentioned above, the “tick” event handler is a place where the magic happens – calculation of node parameters. In our case, a bubble has 4 parameters:Horizontal position
Vertical position
Radius
Color
It seems to be working, what’s next?
We’ve implemented the approach, described in the guide I’ve mentioned above. Everything works as supposed to, all of the bubbles spread and flow beautifully, and they bypass each other, stop at their places… But something’s not right… If you look at a live example from the article, you’ll see that even though the groups have different centres, bubbles themselves interact with each other no matter which group they belong. This creates a common force that pushes groups from each other. In the example from the article there are only 3 groups, but in our case there were 7 of them. Trust me, it looked dreadful: at times a group of bubbles were repulsed by other groups to a distance of 1,5-2 scale divisions. It confused a user, forcing him to calculate how far the necessary group was from the central one, if there had been one.![bad](/uploads/pages/88/bad.webp)
![good](/uploads/pages/88/good.webp)