Making an interactive bubble chart with D3 v. 4
Making an interactive bubble chart with D3 v4
Transcript
all right so this is going to be a
series of tutorials on how to make a
bubble charts in d3 Interactive bubble
charts specifically with d3 version 4 so
it's a little bit different than version
3 so it might be useful if you did it
with 3 and will not 3 to 4 a bubble
chart if you don't know it's a chart
like this where everything is a bunch of
bubbles and the magic thing with it
being interactive is we are going to be
able to sort things like this and split
them up into different segments based on
certain categories of our data so let's
get started this is what we have right
now we have a light-gray SVG and then a
couple circles huddling up in the top
left hand corner so let's look at our
code and let's look at our data first
our data is a series of musical artists
and the number of millions of albums
they have sold worldwide this is kind of
fake as well and then there is a decade
as to whether they are pre or post 2000
so we are going to resize these bubbles
to be different sizes we're going to
have cluster them around the middle and
we're going to split them into groups
based on whether they are pre or post
2000 so our code itself as it stands is
pretty simple we have a height and we
have a width of 500 so it's square we
pull up a div this div right here chart
div based on its ID we add an SVG to it
to give it a height and width we put a G
inside and we transform it to go
actually know where it stays exactly
where it was generally when you have a
d3 visualization you have all kinds of
margins and there's all kinds of math to
make the height and width and then you
transform in order to push your G in a
little bit to give margins around the
outside you don't need to do that with
force diagrams this force diagrams don't
care about margins
then we pull in sales CSV which is the
CSV we were looking at in Excel and we
draw circles so for every single data
point we create a circle we give it a
radius of 10 a fill of light blue in a
class of artists so that's what we're at
right now and if we inspect we have a
whole lot of circles here in their own
upper left-hand corner because this is 0
0
according to SVG and according to d3 so
normally what we would do is we would
have a scale we would have a scale for
the x-axis weaving of a scale for a
y-axis and we would position each one of
these circles independently so let's
just move them all to the same place for
example so see X of 100 and see Y of
let's say 300 I'm going to save that
refresh and now all of our bubbles are
right here it looks just like one bubble
but it is actually millions upon
millions of bubbles right here one for
every one of our artists so what we want
to do on in order to get to the New York
Times visualization is we need to use
something called d3 force d3 force is a
module that implements a velocity V
relate numerical integrator for
simulating physical forces on particles
what this means is if you don't want to
be intimidated don't read the
documentation for d3 force it's not very
user-friendly but hopefully this
tutorial will be user-friendly so what
we need to do is we need to make forces
that act on these bubbles to put them in
the place that we want them to go so
first of all we want all of our bubbles
to kind of cluster in the middle so
there are a few ways to do this but the
one way to do it that all of these
methods have in common is we need to
create a simulation so we are going to
create a simulation that we're going to
call it simulation and it is going to be
a force simulation so what a force
simulation does is it takes every single
one of these circle
and it applies forces to them in order
to get them to go to a certain place so
we are going to want all of ours to go
towards the center so what we need to do
is we create our for simulation up here
and then we are going to use it so first
thing we need to do is we need to feed
it all of our data so we're going to do
dot nodes data points one thing you will
see in a lot of d3 run tutorials but
examples of force diagrams is they're
going to use node if nodes a whole lot
and it just means the circles but it
doesn't always just putting the circles
but usually every node is one of those
circles okay so we're going to feed the
simulation our nodes we're going to save
we're going to refresh and everything is
the same as it was before so what has to
happen is these nodes need to be pushed
down here by the simulation and so what
you're going to do is a simulation is
like a clock it takes at exit exit exit
ticks in every single time let's say a
second goes by it's going to update the
position of all of your nodes of all of
your circles here but you need to write
the code that fires on every tick of the
clock on every tick of the simulation so
we are going to make a function called
ticked and every single time the
function is called it is going to go
grab those circles which we created up
here and we are going to set their CX to
be DX and their CY to be d dot Y now
what this means is when we feed our
simulation these nodes it's going to
automatically update all of our data
points with the CX and or the X and the
y that it wants them to be at so then
every single time we go through this
tick we need to update our circles with
the X
that our data points know about so in
order to make this happen on every
single tick we go arm tick tick
so every single time there's a tick of
the clock fire this code here called
ticked so save it refresh and there
seems to be something happening over
there all the circles are indeed being
pushed around a little bit by a force
but these numbers seem kind of random
and that's because right now our
simulation doesn't know where to put all
of these circles doesn't know what we
want them where we want them to go what
forces we want to act on them so we're
going to add two forces so simulation is
a collection of forces about where we
want our circles to go and how we want
our circles to interact so in order to
add a force you do dot force and then
you give it a name and then you define
the force right there so the first thing
we're going to do is we need to create a
force to push everything towards the
middle now there are a few ways to do
this but the most flexible is a force
called force X another force called
force Y so force X forces it to go
somewhere along the x axis of force Y
for is it to go somewhere along the y
axis so right now this is 0 0 and this
is width height so let's start with the
X force and we're going to try to push
everything to be in the middle so if we
do the math this is 0 this is with this
is with divided by 2 so let's create a
new force we'll call it X and then we
will say we want a new force acts and we
want it to send everything to width
divided by 2 and we want it to be a
little weak I believe strength is a
number between 0 & 1 in a lot of making
a force simulation as playing around
with those numbers to see the right
collection of strengths
so we are going to save this we are
going to refresh and hey look at that it
pushes everything towards the middle
maybe if we make it a little bit
stronger it'll push a little bit more
quickly so let's try 0.05 hey look at
that it pushes them all towards the
middle so what's happening is we're
creating our circles here after we've
read in our data so we read in our data
data points we make a circle for every
data point we say we've created a
simulation here's all of our data and
every single time there's a click of the
top tick of the clock run this function
and reposition our circles this stuff
here is kind of magic you're really
going to cut and paste this every single
time you have a simulation so you don't
necessarily have to worry about what's
happening under the hood but every
single time this tick happens on the
simulation looks at all of the forces
that we've applied and says where should
all of our nodes be where should all of
our circles be and right now we have one
force that tries to push everything on
the x-axis to the middle and it's not a
very strong force but it's enough to get
everything there so in the end it loads
it up and it pushes everything towards
the middle until they're all chilling
out at with / - so we also want them to
go towards the center of the page on the
y-axis so it's the exact same thing
except instead of width divided by two
it's going to be pi divided by two so
I'm just going to cut and paste this to
add a new force we're going to call this
force Y instead of force X it is going
to be force Y and we're going to send it
to height divided by two so now there
are two forces acting on all of our
circles one pushing it towards the
center on the x axis and one pushing it
towards the center on the y axis and
there you go they wonderfully settle
right in the middle now we are using a
force
of course why there's another force
called force center but that's not very
important to us right now
so what we want to do is the big problem
and all of our circles are in the middle
but they're also all on top of each
other so even though you can see it's
wiggling around a little bit
exactly where they are because these
numbers aren't all exactly the same but
they're the same enough that we can't
see our circles so what we want to do is
not have our circles collide so let's
say step 1 get them to the middle step 2
don't have them collide now luckily
enough there's a force and it is called
force collide and the point of that
force is to make things not collide so
let's have a new one call it collide d3
force collide and we're just going to
leave that there we're going to run it
we're going to see what happens then
they look like they've made a slightly
larger circle but nothing meaningful so
when we made Force X we gave it to X
that we want it to end up that when we
did force Y we gave it the Y that we
wanted to end up that when we create a
force collide we give the radius of the
area that we want the collision to avoid
so let's just try five so we can see the
circles are a little less colliding
let's say we made that 7 they're a
little bit further apart now let's make
it 10 and now you can see that they're
all evenly spaced so y 10 well if we go
and look at our code we see that right
here the circles have a radius of 10 so
as long as the radius of the circle
matches the radius of the force collide
of you're not going to have any overlap
between circles
so this looks pretty nice so far the
only issue is we would like these
circles to be bigger and smaller and
we're going to base that on the album
sales column here so let us make a scale
our radius scale it is going to be a
square root scale because it is the
radius of a circle the smallest number
of albums that are sold was 1 million I
believe that Fetty WAP yes and the
largest number is 300 so we're going to
say input somewhere between one and
three hundred and the output let's think
our smallest circle 10 and our largest
one may be a radius of KT so we'll save
that there and then we will use it when
you create our circles so instead of
always making a tent we're going to have
a function return' scale square root D
sales so every time we have a circle
that will set the radius based on the
sales column using this scale that we
just made so give it a save give it a
refresh nope scale square root is not
defined what did I do wrong here Oh
oh okay here's what I did instead of
scale square root here this is radius
scale obviously okay so now we have
another problem the circles are the
right size but they are colliding on top
of each other because what we said in
our code was always make the force
collide to be a 10 always make the let's
say radius of the barrier 10 and because
not all of these are ten now there is a
ton of overlap so the magic thing about
for simulation is instead of just
feeding everything numbers just like how
we changed 10 radius to be specific to
that one data point and we added a
function we can do the same thing with
force collide so what force collide to
be the same for every single circle
every single data point we say okay it's
always going to be Ted but if we want
each of them to have a different
collision force we can add a function in
here so I just set this to be 10 I think
it's good practice every time you
replace a number with the function just
to make sure you did things right put
the same number here so we had force
collide 10 and now I have a function
that always returns 10 so yes it looks
the same the error consults fine
everything's good so what we need to do
is we need to make this collision force
be the same as our radius so if we have
returned radius scale D sales we can
just make the exact same thing happen up
here so as the circle gets bigger the
collision force will also get bigger Hey
look at that wonderful you can also if
you want to add a little bit of extra
spacing between all of these bubbles you
can maybe add +1 to that scale and
you'll push it out and it'll look it'll
look beautiful so one thing that I
didn't talk about is where these names
come from the X and the y and the
collide but you can actually name them
anything so I can call this anti
colliding and I could call this X
towards the center and Y towards the
center and it will still work fine it's
just if you end up wanting to replace or
edit these forces later you're going to
need to use their names butts so one
more quick thing before we go I'll
review this in the next video as well
but we are using the center as width / 2
height divided by 2 now sometimes you
want to have the middle of this b:00 so
you would like to say force X 0 force y
0 they actually default to being 0 so we
could even get rid of those numbers so
if we see right here they're clustering
around 0 0 if I get rid of this they are
still clustering around 0 0 one thing I
could do is we have this G that
everything is hiding inside of right we
examine this we have an SVG and inside
that we have a G with all of our circles
you could say translate width / - height
/ - and what that will do is it will
push everything down to have the middle
point be 0 0 now this isn't always the
best thing to do just depending upon
high are going to be positioning your
circles later I just wanted to give you
a shout about that here just in case you
see it in other people's code so we are
going to go back back back back back to
the width of Ida by 2 and height divided
by 2 and there you have it we have made
a bubble chart where it is going to push
everything
towards the center oh let's just we'll
do we'll do one more tiny thing one more
tiny thing to make it a little bit nicer
these circles are the same as any other
circles that you might work with so
let's say on click we can you know
console dot log and examine this is
Madonna that's Hollow notes and then we
have the Eagles over here so anything
even though these are moving around and
these are wiggling you can still use
tooltips you can still use transitions
and you can still use all of the normal
things that you would use in a d3
visualization all the for spit is doing
on between here and here is it's going
to move all of these forces around for
you so instead of setting the CX and CY
according to the scale the CX and CY
will be said by the simulation in this
function so that wasn't very much extra
code all we did was we added a few
different forces and then we said hey
apply these forces to all of our circles
and we made a pretty impressive graphic
so alright
series of tutorials on how to make a
bubble charts in d3 Interactive bubble
charts specifically with d3 version 4 so
it's a little bit different than version
3 so it might be useful if you did it
with 3 and will not 3 to 4 a bubble
chart if you don't know it's a chart
like this where everything is a bunch of
bubbles and the magic thing with it
being interactive is we are going to be
able to sort things like this and split
them up into different segments based on
certain categories of our data so let's
get started this is what we have right
now we have a light-gray SVG and then a
couple circles huddling up in the top
left hand corner so let's look at our
code and let's look at our data first
our data is a series of musical artists
and the number of millions of albums
they have sold worldwide this is kind of
fake as well and then there is a decade
as to whether they are pre or post 2000
so we are going to resize these bubbles
to be different sizes we're going to
have cluster them around the middle and
we're going to split them into groups
based on whether they are pre or post
2000 so our code itself as it stands is
pretty simple we have a height and we
have a width of 500 so it's square we
pull up a div this div right here chart
div based on its ID we add an SVG to it
to give it a height and width we put a G
inside and we transform it to go
actually know where it stays exactly
where it was generally when you have a
d3 visualization you have all kinds of
margins and there's all kinds of math to
make the height and width and then you
transform in order to push your G in a
little bit to give margins around the
outside you don't need to do that with
force diagrams this force diagrams don't
care about margins
then we pull in sales CSV which is the
CSV we were looking at in Excel and we
draw circles so for every single data
point we create a circle we give it a
radius of 10 a fill of light blue in a
class of artists so that's what we're at
right now and if we inspect we have a
whole lot of circles here in their own
upper left-hand corner because this is 0
0
according to SVG and according to d3 so
normally what we would do is we would
have a scale we would have a scale for
the x-axis weaving of a scale for a
y-axis and we would position each one of
these circles independently so let's
just move them all to the same place for
example so see X of 100 and see Y of
let's say 300 I'm going to save that
refresh and now all of our bubbles are
right here it looks just like one bubble
but it is actually millions upon
millions of bubbles right here one for
every one of our artists so what we want
to do on in order to get to the New York
Times visualization is we need to use
something called d3 force d3 force is a
module that implements a velocity V
relate numerical integrator for
simulating physical forces on particles
what this means is if you don't want to
be intimidated don't read the
documentation for d3 force it's not very
user-friendly but hopefully this
tutorial will be user-friendly so what
we need to do is we need to make forces
that act on these bubbles to put them in
the place that we want them to go so
first of all we want all of our bubbles
to kind of cluster in the middle so
there are a few ways to do this but the
one way to do it that all of these
methods have in common is we need to
create a simulation so we are going to
create a simulation that we're going to
call it simulation and it is going to be
a force simulation so what a force
simulation does is it takes every single
one of these circle
and it applies forces to them in order
to get them to go to a certain place so
we are going to want all of ours to go
towards the center so what we need to do
is we create our for simulation up here
and then we are going to use it so first
thing we need to do is we need to feed
it all of our data so we're going to do
dot nodes data points one thing you will
see in a lot of d3 run tutorials but
examples of force diagrams is they're
going to use node if nodes a whole lot
and it just means the circles but it
doesn't always just putting the circles
but usually every node is one of those
circles okay so we're going to feed the
simulation our nodes we're going to save
we're going to refresh and everything is
the same as it was before so what has to
happen is these nodes need to be pushed
down here by the simulation and so what
you're going to do is a simulation is
like a clock it takes at exit exit exit
ticks in every single time let's say a
second goes by it's going to update the
position of all of your nodes of all of
your circles here but you need to write
the code that fires on every tick of the
clock on every tick of the simulation so
we are going to make a function called
ticked and every single time the
function is called it is going to go
grab those circles which we created up
here and we are going to set their CX to
be DX and their CY to be d dot Y now
what this means is when we feed our
simulation these nodes it's going to
automatically update all of our data
points with the CX and or the X and the
y that it wants them to be at so then
every single time we go through this
tick we need to update our circles with
the X
that our data points know about so in
order to make this happen on every
single tick we go arm tick tick
so every single time there's a tick of
the clock fire this code here called
ticked so save it refresh and there
seems to be something happening over
there all the circles are indeed being
pushed around a little bit by a force
but these numbers seem kind of random
and that's because right now our
simulation doesn't know where to put all
of these circles doesn't know what we
want them where we want them to go what
forces we want to act on them so we're
going to add two forces so simulation is
a collection of forces about where we
want our circles to go and how we want
our circles to interact so in order to
add a force you do dot force and then
you give it a name and then you define
the force right there so the first thing
we're going to do is we need to create a
force to push everything towards the
middle now there are a few ways to do
this but the most flexible is a force
called force X another force called
force Y so force X forces it to go
somewhere along the x axis of force Y
for is it to go somewhere along the y
axis so right now this is 0 0 and this
is width height so let's start with the
X force and we're going to try to push
everything to be in the middle so if we
do the math this is 0 this is with this
is with divided by 2 so let's create a
new force we'll call it X and then we
will say we want a new force acts and we
want it to send everything to width
divided by 2 and we want it to be a
little weak I believe strength is a
number between 0 & 1 in a lot of making
a force simulation as playing around
with those numbers to see the right
collection of strengths
so we are going to save this we are
going to refresh and hey look at that it
pushes everything towards the middle
maybe if we make it a little bit
stronger it'll push a little bit more
quickly so let's try 0.05 hey look at
that it pushes them all towards the
middle so what's happening is we're
creating our circles here after we've
read in our data so we read in our data
data points we make a circle for every
data point we say we've created a
simulation here's all of our data and
every single time there's a click of the
top tick of the clock run this function
and reposition our circles this stuff
here is kind of magic you're really
going to cut and paste this every single
time you have a simulation so you don't
necessarily have to worry about what's
happening under the hood but every
single time this tick happens on the
simulation looks at all of the forces
that we've applied and says where should
all of our nodes be where should all of
our circles be and right now we have one
force that tries to push everything on
the x-axis to the middle and it's not a
very strong force but it's enough to get
everything there so in the end it loads
it up and it pushes everything towards
the middle until they're all chilling
out at with / - so we also want them to
go towards the center of the page on the
y-axis so it's the exact same thing
except instead of width divided by two
it's going to be pi divided by two so
I'm just going to cut and paste this to
add a new force we're going to call this
force Y instead of force X it is going
to be force Y and we're going to send it
to height divided by two so now there
are two forces acting on all of our
circles one pushing it towards the
center on the x axis and one pushing it
towards the center on the y axis and
there you go they wonderfully settle
right in the middle now we are using a
force
of course why there's another force
called force center but that's not very
important to us right now
so what we want to do is the big problem
and all of our circles are in the middle
but they're also all on top of each
other so even though you can see it's
wiggling around a little bit
exactly where they are because these
numbers aren't all exactly the same but
they're the same enough that we can't
see our circles so what we want to do is
not have our circles collide so let's
say step 1 get them to the middle step 2
don't have them collide now luckily
enough there's a force and it is called
force collide and the point of that
force is to make things not collide so
let's have a new one call it collide d3
force collide and we're just going to
leave that there we're going to run it
we're going to see what happens then
they look like they've made a slightly
larger circle but nothing meaningful so
when we made Force X we gave it to X
that we want it to end up that when we
did force Y we gave it the Y that we
wanted to end up that when we create a
force collide we give the radius of the
area that we want the collision to avoid
so let's just try five so we can see the
circles are a little less colliding
let's say we made that 7 they're a
little bit further apart now let's make
it 10 and now you can see that they're
all evenly spaced so y 10 well if we go
and look at our code we see that right
here the circles have a radius of 10 so
as long as the radius of the circle
matches the radius of the force collide
of you're not going to have any overlap
between circles
so this looks pretty nice so far the
only issue is we would like these
circles to be bigger and smaller and
we're going to base that on the album
sales column here so let us make a scale
our radius scale it is going to be a
square root scale because it is the
radius of a circle the smallest number
of albums that are sold was 1 million I
believe that Fetty WAP yes and the
largest number is 300 so we're going to
say input somewhere between one and
three hundred and the output let's think
our smallest circle 10 and our largest
one may be a radius of KT so we'll save
that there and then we will use it when
you create our circles so instead of
always making a tent we're going to have
a function return' scale square root D
sales so every time we have a circle
that will set the radius based on the
sales column using this scale that we
just made so give it a save give it a
refresh nope scale square root is not
defined what did I do wrong here Oh
oh okay here's what I did instead of
scale square root here this is radius
scale obviously okay so now we have
another problem the circles are the
right size but they are colliding on top
of each other because what we said in
our code was always make the force
collide to be a 10 always make the let's
say radius of the barrier 10 and because
not all of these are ten now there is a
ton of overlap so the magic thing about
for simulation is instead of just
feeding everything numbers just like how
we changed 10 radius to be specific to
that one data point and we added a
function we can do the same thing with
force collide so what force collide to
be the same for every single circle
every single data point we say okay it's
always going to be Ted but if we want
each of them to have a different
collision force we can add a function in
here so I just set this to be 10 I think
it's good practice every time you
replace a number with the function just
to make sure you did things right put
the same number here so we had force
collide 10 and now I have a function
that always returns 10 so yes it looks
the same the error consults fine
everything's good so what we need to do
is we need to make this collision force
be the same as our radius so if we have
returned radius scale D sales we can
just make the exact same thing happen up
here so as the circle gets bigger the
collision force will also get bigger Hey
look at that wonderful you can also if
you want to add a little bit of extra
spacing between all of these bubbles you
can maybe add +1 to that scale and
you'll push it out and it'll look it'll
look beautiful so one thing that I
didn't talk about is where these names
come from the X and the y and the
collide but you can actually name them
anything so I can call this anti
colliding and I could call this X
towards the center and Y towards the
center and it will still work fine it's
just if you end up wanting to replace or
edit these forces later you're going to
need to use their names butts so one
more quick thing before we go I'll
review this in the next video as well
but we are using the center as width / 2
height divided by 2 now sometimes you
want to have the middle of this b:00 so
you would like to say force X 0 force y
0 they actually default to being 0 so we
could even get rid of those numbers so
if we see right here they're clustering
around 0 0 if I get rid of this they are
still clustering around 0 0 one thing I
could do is we have this G that
everything is hiding inside of right we
examine this we have an SVG and inside
that we have a G with all of our circles
you could say translate width / - height
/ - and what that will do is it will
push everything down to have the middle
point be 0 0 now this isn't always the
best thing to do just depending upon
high are going to be positioning your
circles later I just wanted to give you
a shout about that here just in case you
see it in other people's code so we are
going to go back back back back back to
the width of Ida by 2 and height divided
by 2 and there you have it we have made
a bubble chart where it is going to push
everything
towards the center oh let's just we'll
do we'll do one more tiny thing one more
tiny thing to make it a little bit nicer
these circles are the same as any other
circles that you might work with so
let's say on click we can you know
console dot log and examine this is
Madonna that's Hollow notes and then we
have the Eagles over here so anything
even though these are moving around and
these are wiggling you can still use
tooltips you can still use transitions
and you can still use all of the normal
things that you would use in a d3
visualization all the for spit is doing
on between here and here is it's going
to move all of these forces around for
you so instead of setting the CX and CY
according to the scale the CX and CY
will be said by the simulation in this
function so that wasn't very much extra
code all we did was we added a few
different forces and then we said hey
apply these forces to all of our circles
and we made a pretty impressive graphic
so alright