Making a world map with D3

Making a world map with d3, topojson, and a csv
hello this is the first in a series of
videos about how to make maps in d3
version 4 so this map here this first
one is going to be a map of the world
and it's going to have a few capitals on
it so it's going to be very very simple
map I'm making maps in d3 is honestly
pretty simple compared to a lot of the
other things you can do so if you've
been following along with other videos
you'll probably be very relieved to see
what's going on here alright so let's
start off by looking at our basic
JavaScript or visualization Jas this is
the standard sort of JavaScript that we
use whenever we build d3 visualizations
we start off by creating a margin height
width when we select something on the
page we put an SVG in it we set its
height and width we put a group object
inside of that move it around so we have
a margin and then we queue up what we're
going to import and then we start
processing it so the one thing that's
changed between this visual and the
other visuals that we've done is right
here for our file that we're importing
it's not a CSV file 99 times out of 100
we read in files that are CSVs later on
we'll read in this capital CSV file but
if we look we see it is a dot topo JSON
file generally this would just be dot
JSON but the file itself is something
called topo JSON and if we look at it it
looks real real pleasant on what we need
to know for this visual is topo json is
basically a fancier nicer form of a file
format called geo json so if we go to
goj song geo it is a wonderful place
where you can build maps in this format
called geo json so if we look on the
right
we see there's a type and features and
all kinds of coordinates that make up
this line string maybe if we put down
some markers we can see that as well now
this is geo JSON and the problem with
geo JSON is that it is very very very
large if you want to have a map of say
all of the counties in the United States
you are talking a long download time for
your user and because the point of d3 is
generally to produce things for the web
you want to make sure that your file
sizes are small so topo JSON and if I
can hop on over to github there's it's
up to version 2 now and it takes away
pretty much all the fun functionality of
version 1 so we'll refer to another
video on how to use topo JSON um but
it's it's a waterful file format and you
should always be using it on whenever
you are pulling in map data or
geographic data for d3 well not always
so a CSV file is really good for point
data because you just have a latitude
and longitude but for anything else
shapes counties states countries
anything like that you're going to use
topo JSON so alright we have this file
let us spin up our server and visit our
page so this is the first one this is
the world and hopefully there's no
problems initially now everything is
good alright so right now we have an SVG
it doesn't have anything in it I'm going
to add a little bit of a background on
it just so you can see something later
on so I'm going to say SVG let's have
your background be ef ef ef ok so inside
of our visualization is we are pulling
in the
three JSON or we're reading in World Cup
Oh JSON we're saying please process it
with the d3 JSON processor and now we're
going to go down here and I just want
you to see what the data looks like so
we're going to console.log the data
refresh and come over here so inside of
this top Oh JSON object
it's got arcs it's got bounding box it's
got objects it's got transforms um it's
real it's real exciting the stuff that
we're interested in is inside of objects
every single time you read in a topo
JSON file
there will be an object section and
those objects will have all of the
information that you need to draw your
geographic bit so for example right now
we have countries this is going to be a
series of countries that we're going to
draw on this map you might also have
States maybe you'd have you could have
an infinite number of different objects
in here but you're going to treat them
all separately so how do we map these
countries well the first thing that we
need to do is convert from topo JSON
into a format that is usable by us if we
go back to our index file we can see
that we are including topo JSON version
1 nsj so we're pulling in d3 then we're
pulling on top of JSON and then we're
including visualization GIS which is our
file so just make sure that any time
you're doing Maps you include a topo
JSON as a library so we are going to use
a something called topo JSON feature
we're just going to extract all of the
countries from our topo JSON and turn it
into something we can use
so VAR countries equals topo json dot
feature topo json dot feature you have
to send it to different things first you
have to send it the route of your data
which is basically your top of json file
which for us is data and then you have
to send it the specific data that you're
looking for so in this case
this is our data and then we have
objects and then we have countries so we
are going to be looking for data objects
countries every single time you are
reading in topo JSON you are going to
want a consult log and then look inside
of objects and then figure out what the
key name is where your data is living so
ours as I've said a hundred times his
country's yours might be States here's
my piece some strange code from the US
Census Bureau anything like that and
then we do dot features so every single
time that you pull in topo JSON you are
going to write this and just to confirm
that we got some countries out of this
I'm going to save I'm going to refresh
Hey look at that
this big long array full of a bunch of
different countries I mean so every
country has let's see it has an ID as a
type properties and geometry so we can
see that geometry seems to have maybe
latitude and longitude on hand side
properties has color and name so yes
this is all of our country data so when
we are trying to draw countries
countries are shapes and as we all know
shapes mean we are going to make path
objects so let's just pretend that this
is not topo JSON that is not something
we've never done before we have what 242
different countries in here I believe
242 yes so let's just do an SVG select
all our pads we could just do path here
but let's be a little more proper of
let's call it dot country we're going to
give it a class of country will bind our
countries that will do it enter we'll
add a path for every single country and
then we will set it to be a class of
country just so this and this match up
so we could save it if we want we can
refresh and if we wanted to look at this
we could see that we now have one path
for every single country
so the thing is about pads is they need
only one attribute in order to show up
they need an attribute that is D now D
is basically a list of coordinates and a
certain way to move between all those
coordinates of in order to draw a shape
but how do we turn this data here
this data here maybe this these
properties maybe this geometry how do we
turn that into something that we can use
to draw a shape inside of D all right
we're going to do two things first off
we need to make a projection so
projection when you have a globe it's
round as we all know I hope we all know
our screen however is flat so we need a
way to translate between a round globe
and say okay I know the globe is round
but we need to display it on the screen
so change those numbers change those
latitude and longitudes a very specific
way to get it to end up on a flat screen
I'll have another video about that but
for now here's what we're going to do
there are several different projections
projections is what you use to convert
from a globe to something flat there are
several different projections we are
using a pretty standard one called
Mercator and in order to use it just d3
geo Mercator we want to Center it in the
middle of our visual so we are going to
do with / - height / - this is going to
Center it later on I will scale it to
zoom in or out out a certain amount but
for now let's just stick with this very
basic projection so even though we now
have a projection we need some way
that's very good for let's say points so
I say here's a latitude and longitude
and the projection will say here is an x
+ y I say here's another latitude and
longitude for another city and it says
here is the action Y on the screen that
that city
should be displayed up but what we're
going to do now the second step is a
shape is built on a ton of different
points it's basically drawing a line so
in the same way that when we made line
graphs we had a line generator we need
to need to do the same thing for a mat
visual so far path equals d3 geo path
projection projection every single time
you have shapes on a map you were going
to do these two things sometimes you
know we'll make another map where this
changes here but maybe 100 times out of
100 you are going to have this line of
our path equals d3 geo path dot
projection projection and this is just
the way that that long series of dots
that make up a shape will be filled in
and will turn into the D of a shape so
let's do this all right
we are going to take that path variable
that we made up here on this geo path
and we are just going to feed it right
to D we're going to save and there we go
we have very easily and very simply put
together a map there's a problem though
and the problem is that we are zoomed in
a little bit too far so what we're going
to do is we're going to do two things
first
we are going to go to our projection and
we're going to try to scale it you can
put in a ton of different numbers for
scale and a lot of the game you're
playing with a visual is going to be
inventing the right number for your
scale so I'm going to save this start it
100 wow that actually doesn't seem that
bad if you started off with scale and
you did scale so you scale 10 you're
going to end up very very far away and
then if you did scale let's say 1000
you're going to end up much much closer
so you end up using scale in order to
zoom in or zoom out so we're just going
to stick 200 and it's going to look fine
and we want to change the way that the
use shapes look so usually usually when
you're doing pads you go down here and
you do you know attr fill and we'll make
it something a kind of light si si si si
si si si now I'm so nice no gray bit
when you do maps it's I would say
probably more important than when you do
other visuals instead of doing it via
attr fill your good old one or write
some CSS for this so we're going to get
rid of that and we're going to thank
okay our class for these is country so
let's go into index we'll make a new
rule and we'll make the fill for these
be on si si si si si si
a white background here alright and
maybe we'll draw some lines around each
of these so let's make our stroke be a
darkish black and we'll thin those lines
out a little bit so stroke width may be
0.5 okay that looks a lot better that
was like a row map okay so it was
remarkably easy to draw this map all it
took was a projection a geo path this
line to pull the features out of our top
of JSON and then we just did our normal
data binding enter append and just added
that ATT Rd path and then life is is
wonderful now it's great because you can
make you can drink these just like you
would circles just like you would
rectangles just like you would anything
else for example we could have on click
d3 select this attr fill yellow so every
single time we click on one of these
paths it is going to turn the fill to
yellow it did not work clicked ignore
that did not work why would that not
apart
oh it's been overridden by the CSS so
we're going to have to do instead is a
class selected true so this is going to
do is it's going to say add the class of
selected to the element that is being
quite this says get the element this is
get the the shape on the map and you do
dot class and it says you know add the
class selected so we are going to say
selected the fill is yellow wonderful
right we could also do this for hovering
we could say on mouse-over add the class
selected and then on Mouse out remove
the class selected remove the class
selected add the class selected and so
there we go we get a nice kind of hover
event as we go over these now one more
thing we're going to do adding shapes is
this very easy piece here adding dots is
a little little bit more complicated so
here's what we're going to do we are
going to pull in one more file we're
going to defer we're going to do d3 CSV
and we're going to pull in capitals dot
CSV which is this file right here we are
going to because it is another thing we
are deferring it is the second file here
so we'll end up being the third thing
here so data is world topo JSON and now
capitals is going to be capitals dot CSV
and if you want to make sure that we're
doing this console dot log
Capitol's save or trash and Hey look at
that I have a whole bunch of capitals um
coming along there okay so for our
capitals we would like to put dots down
for each of them so SVG dot select all
and we're going to call these maybe city
circles we're going to bind our data
enter a pen because these are going to
be circles we're going to add circles to
them and we will make them not very big
just give them an RF two now when we
have a circle we need to set two things
when you set a CX and a Cy so right now
I'm making all of these circles show up
on top of one another I'm at ten ten
so I'm going to refresh just make sure
they show up and hey look at that we
have some circles there that actually
look like boxes but such as life okay so
what we need to do is each one of these
if we look at the data itself there is a
Latin column and there is a long column
and we need to convert that into
something that is usable with X
so because the x CX is going to be
different for each of these we're going
to throw in a function here and because
the CY is going to be different for each
of these we are going to throw in a
function there now let's just look at
our data point just for kicks will
refresh and we see yes we have a
latitude and we have a longitude so how
are we going to convert this to an x and
a y that shows up on the page so if we
think back we made this fun thing here
on this projection and what the role of
the projection is is to convert latitude
and longitude England globe to something
that will exist on the screen so let's
just feed our latitude and longitude on
to that projection and see what we get
back
so let's save our towards equals
projection then is a list long and DDOT
lads will console dot log that so we're
saying hey there's a projection it's the
way to translate from a globe to a flat
world to a flat screen and then we're
going to give it the latitude and
longitude so these are the column names
from here long and lat
I didn't make those up alright we
refresh and now hey look at these
numbers these numbers are x and
y-coordinates
now we are just setting we're setting
the CX right now so we don't need both
of these numbers right we only need one
of them we only need two X so X is the
first one X is zero so we are going to
return towards zero now the weird thing
is that I mean it's kind of weird in
order to get the x coordinate we don't
just look at the latitude we don't just
look at the longitude we have to feed
both the latitude and longitude into the
projection get the coordinates and then
only return one of the coordinates so we
do the same thing for the cy except
instead of only returning the X we are
only going to return the Y which is 191
in this case and the X is 270 and
refresh and look at that we have some
wonderful little cities showing up on
our map now we're going to do the exact
same thing
for the text if we were smart we could
have done G elements for each of these
and added the dot out of the circle and
out of the text inside of that but we're
not very smart so we're just going to do
these separately so in the same way that
we did select all city circle data
capitals blah blah SVG select all city
label data capitals enter append text
now the
that I like to do text labels is I like
to set the X&Y; to be right on top of the
dot so we're going to change this to X
we're going to change this to Y and then
we're going to say text this is a
capital just to make sure that it works
because text elements Oh attr
class city label these need x and y
coordinates and then they need this text
bit here so let's save let's refresh and
there we go the absent text there
instead of this is a capital function D
let's just look at our data real quick
to see how we get the name out of it we
scroll down and we just do D dot name so
we are going to do return D name so it's
the name and now first thing we're going
to make this a bit smaller let's make it
a bit smaller using CSS actually so
we're going to steal this class here the
city label class we're going to go in
here to our index we're going to go dot
city label font size I'll just make it
10 pixels nice and tiny okay that's nice
and small and now we need to offset it
to the right and down a little bit so
the way we do that is like I said we
could add you know ten-year we could add
5 here but I like to stick with DX which
is the offset on the x-axis and dy which
is the offset on the y-axis so I'm going
to save I'm going to refresh and now
you'll see that each one of those labels
was pushed 10 pixels to the right and 5
pixels down which was clearly far too
much so maybe we want two pixels down
and maybe five pixels over so two pixels
down five pixels over give it a save
we're looking good so
you can do on this map you can't see
these labels necessarily very well so
you can add something like a text shadow
in order to kind of make it stand out
you could set the size of these circles
um based on other bits of data you could
change the color of these based on data
that comes in through your topo JSON but
we'll save that for later
I vote for now this is pretty good we've
made a map and we've put some dots on it
and that's really all all anyone can
expect audibles
Skill:
Expertise:

Tutorial on how to make maps in D3 version 4

Contributor: Jonathan Soma

Video 1 of 2