Skip to content
NieneB edited this page Aug 10, 2017 · 27 revisions

In D3 step 1 we will set up the basics to show a simple map with D3.

Setting up the basics

▶️ Open your text editor.

▶️ Start with a basic HTML page.

▶️ Save the file in a yourDirectory and call the file index.html.

<!doctype html>
<html lang="nl">
<html>
  <head>
    <meta charset="utf-8">
    <title>basic HTML</title> 
  </head>
  <body>
    <h1>Example</h1>
  </body>
</html>

▶️ Go to d3js.org. Scroll down and download the newest release (d3.v4.min.js). Or use the snippet provided below.

Because we already have utf-8 stated in the <head> we do not have to specify it in the script. (utf-8 makes sure all diacritical marks are placed right)

<script src="https://d3js.org/d3.v4.min.js"></script>

JS JavaScript libraries are often placed in the head. Though, it is best to place them as far as possible to the bottom of the body. This is much quicker while loading!

▶️ Change the title to “My first map in D3”.

Now your file will look like:

<!doctype html>
<html lang="nl">
<html>
  <head>
    <meta charset="utf-8">
    <title>My first map in D3</title> 
  </head>
  <body>
    <H1>Example</H1>
    <script src="//d3js.org/d3.v4.min.js"></script> 
    <script> your code goes here </script>
  </body>
</html>

The basics are done! Let's start the code!

Setting up the map canvas

▶️ Replace “your code goes here” with:

<script> 
  //Width and height
  var w = 500;
  var h = 300;

  //Define map projection
  var projection = d3.geoMercator()
    .center([ 30, 40 ])
    .translate([ w/2, h/2 ])
    .scale([ w/4 ]);

  //Define path generator
  var path = d3.geoPath()
    .projection(projection);

  //Create SVG
  var svg = d3.select("body")
    .append("svg")
    .attr("width", w)
    .attr("height", h);
</script>

Some JavaScript explanation:

The double slashes // mark a Single line comment. Any text between // and the end of the line will be ignored by JavaScript (will not be executed). > JavaScript comments can be used to explain JavaScript code, and to make it more readable.

The ; at the end of every statement tells the computer that the statement has ended.

var *stands for variable. Variables store data so that they can be used later on in the program.

What did you do?

ℹ️ First you created to variables with the width and height of your map (named w and h) for your browser screen(in pixels). We need dimensions for the map, for we did not specify those in our css.

//Width and height
var w = 500;
var h = 300;

ℹ️ Next we created a variable projection which contains the projection specifications of the map. D3 provides a range of projections. We use Mercator here which is the most common.

ℹ️ The .centre property we set with longitude and latitude.

ℹ️ .translate, in this way, takes care that our map is in the centre of the area.

ℹ️ .scale is the zoom-level

//Define map projection
var projection = d3.geoMercator()
  .center([30, 40])
  .translate([ w/2, h/2 ])
  .scale([ w/7 ]);

ℹ️ When the projection is created we can use it to transform our geographic data to SVG with the help of D3.geoPath

//Define path generator
var path = d3.geoPath()
  .projection(projection);

ℹ️ Next, we create our 'canvas' where we will display our map. You create a variable and give it a name, for example svg.

ℹ️ d3 is a call to the functions of D3.

ℹ️select, selects one element of the DOM, in this case the <body>.

ℹ️ append, appends a SVG to the 'canvas' called svg

ℹ️ next we also provide the attr (attributes), width and height.

//Create SVG
var svg = d3.select("body")
  .append("svg")
  .attr("width", w)
  .attr("height", h);

Some JavaScript explanation:

JavaScript is an object based language. What we did here is creating several objects with properties and a property is an association between a name (or key) and a value. We can create objects and access their properties in the code. Objects in JavaScript, just as in many other programming languages, can be compared to objects in real life. The concept of objects in JavaScript can be understood with real life, tangible objects.

For example, let's create an object named myCar and give it properties named make, model, and year as follows:>

var myCar = new Object();
myCar.make = 'Ford';
myCar.model = 'Mustang';
myCar.year = 1969;

It can also be written like this:

var myCar = new Object()
  .make = 'Ford'
  .model = 'Mustang'
  .year = 1969;

Do you see the similarities with our code? Instead of creating an Object, we created a d3.geoMercator object!

var projection = d3.geoMercator()
  .center([30, 40])
  .translate([ w/2, h/2 ])
  .scale([ w/7 ]);

You access the properties of an object with a simple dot-notation: objectName.propertyName. So requesting the cars model would be:

myCar.model;
  'Mustang'

We also do this in our code! You will see this happening in the next parts.

Adding Data

To 'bind' your data to the DOM is the next step. With D3 you can connect data like .csv or in our case a GeoJSON file. We will use a GeoJSON with the country shapes of the whole world!

▶️ Download this dataset with the all the countries of the world.

▶️ Right click: Save Page As...

▶️ Place the world.geojson file in yourDirectory.

▶️ Copy the following script, below the previous script (index.html).

// create a new SVG group element
var layerWorld = svg.append('g');

//Load in GeoJSON data
d3.json("world.geojson", function(json) {
  //Bind data and create one path per GeoJSON feature
  layerWorld.selectAll("path")
    .data(json.features)
    .enter()
    .append("path")
    .attr("d", path);
}); 

▶️ Check in your browser if you see a world map.

What did you do?

ℹ️ First we created a new variable called layerWorld which will keep all our data paths together in a group called 'g'.

ℹ️ d3.json( "world.geojson", function(json)) opens the GeoJSON file and puts the data through a function, the data will be called json inside the function.

ℹ️ Now we select all "paths" in the layerWorld and create paths for every feature that we find in our data. enter() and append() will take care for this.

ℹ️ The .attr() option creates the svg paths.

If you open the console and look at the DOM inspector you will see a <path> object is created per country! It wasn't in our HTML file first but D3 took care of that.

  • Click with your right mouse button, choose : Inspect Element
  • Or Press F12

img

‼️ you do not see a map?

Open the debugger

  • Click with your right mouse button, choose : Inspect Element
  • Or Press F12

The debugger shows you the content of your page. But also logs any errors or comments! Go to the tab Web Console to see if it reports anything useful for you.

Do you get something like this:

Uncaught SyntaxError: missing ) after argument list. index.html:19

Then something is wrong in your code! This specific error means a ) bracket is missing on line 19 of our script! Try to fix your error and reload your page.

▶️ Play around with the projection, centre and zoom level.

▶️ Have a look at https://github.com/d3/d3-3.x-api-reference/blob/master/Geo-Projections.md for different projections.

Projection

Projections are what we call the mathematical equations that do the trick of turning the world into some flat shape that fits on a printout or a computer screen. It’s a messy task to do, this transformation - there’s no way to smoosh the world onto a screen without distorting it in some way. You either lose direction, or relative size, or come out with something very weird looking.

projection

▶️ For example, try to zoom in on the Netherlands or the US!

You can find lat long coordinates with this website easily.

var projection = d3.geoMercator()
  .center([4, 52])
  .translate([ w/2, h/2 ])
  .scale(1000);

▶️ Now really try to pimp your map here! Change the colours and play around with the style attributes!

For example, change the background of your web page to black, and give the world map another color, like dark grey:

<style type="text/css">
  body {
    background-color: #000000
  }
  h1 { 
    color: #ffffff
  }
</style>

Do you remember where to put is?

This is for the countries:

.style("fill", "#313030")
.style("stroke", "#5a5959");

It should look something like this now:

img

This should be your code now:

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>basic HTML</title> 
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <style type="text/css">
      body {
        background-color: #000000
      }
      h1 { 
        color: #ffffff
      }
    </style>
  </head>
  <body>
    <h1>Example</h1>
    <script> 
      //Width and height
      var w = 1000;
      var h = 800;

      //Define map projection
      var projection = d3.geoMercator()
        .center([ -100, 45 ])
        .translate([ w/2, h/2 ])
        .scale([ w/2 ]);

      //Define path generator
      var path = d3.geoPath()
        .projection(projection);

      //Create SVG
      var svg = d3.select("body")
        .append("svg")
        .attr("width", w)
        .attr("height", h);

      // create a new SVG group element
      var layerWorld = svg.append('g');

      //Load in GeoJSON data
      d3.json("world.geojson", function(json) {
        //Bind data and create one path per GeoJSON feature
        layerWorld.selectAll("path")
           .data(json.features)
           .enter()
           .append("path")
           .attr("d", path)
           .style("fill", "#313030")
           .style("stroke", "#5a5959");
      }); 
    </script>
  </body>
</html>

➡️ Continue to D3 Step 2