This is Part Two of a four part tutorial on how to make a data-driven map using JavaScript.

The end result is an web map visualising electric vehicle chargepoint locations:

Click map to view live version

In this part we'll load a dataset from the UK's National Chargepoint Registry using D3 and will display each location on the map:


The steps you'll take are:

  • include D3 n your project
  • load the data using D3
  • plot the locations on the map

Include D3.js

Open your work from Part One (or use Part One's pen).

Include D3 by clicking on the cog in the JS panel:

and add to the 'Add External Scripts/Pens' list:

If you wish to save your work you can click the 'Fork' button.

Load the CSV data

You'll now use D3's .csv() function to load the CSV file into your app. This function will request the CSV file and transform it into an array of objects.

Add the following code to the bottom of the JS panel:

.then(function(csv) {
// csv is an array of objects where each object represents a charging point

The above code requests a CSV file named charge-points-slim.csv that's hosted using CodePen's asset hosting. (The CSV file is derived from the original charging points dataset. I've removed several columns to reduce the file size.)

If you wish to load your own data you'll need to host it somewhere (e.g. CodePen's asset hosting, Google Cloud Storage etc.) and replace the URL in the d3.csv() call. Be careful with CORS restrictions.

When D3 receives the data it converts it into an array of objects and the callback function (function(csv) {...}) is invoked. The parameter csv is an array of objects that'll look something like:

"name": "2 Riddons Road",
"latitude": "51.431454",
"longitude": "0.031175",
"postcode": "SE12 9QR",
"chargeDeviceStatus": "In service",
"deviceControllerName": "Source London"
"name": "9 Bath Road Car Park",
"latitude": "51.48092",
"longitude": "-0.419318",
"postcode": "TW6 2AA ",
"chargeDeviceStatus": "Out of service",
"deviceControllerName": "Source London"
"name": "ACE Cafe London",
"latitude": "51.54121",
"longitude": "-0.277943",
"postcode": "NW10 7UD",
"chargeDeviceStatus": "In service",
"deviceControllerName": "Source London"
"name": "Acton Street",
"latitude": "51.52834",
"longitude": "-0.118619",
"postcode": "WC1X 9LZ",
"chargeDeviceStatus": "Out of service",
"deviceControllerName": "Source London"

Notice that each row of the CSV file has been transformed into an object. Each object has a number of properties which correspond to columns of the CSV file.

In the next step we'll iterate through the array and add markers to the map.

Add markers

Start by declaring a global variable data at the top of the JavaScript:

var data;

In the callback function assign csv to data (so that we can access the data anywhere in the code):

.then(function(csv) {
data = csv;

Global variables are fine in small examples such as this. Try to avoid using them in larger projects.

Near the top of the file, just after var data; add a function addMarkers() that iterates through data and adds a marker to the map:

function addMarkers() {
data.forEach(function(d) {
var marker = L.circleMarker([+d.latitude, +d.longitude]);

We're using Leaflet's circleMarker which draws a circle at a given latitude and longitude.

A circleMarker is added by calling L.circleMarker([lat, lon]) where lat and lon are latitude and longitude values. When D3 converts the CSV into an array of objects, the latitude and longitude are strings so we convert them to numbers using the + operator.

Now call addMarkers() in the request callback:

.then(function(csv) {
data = csv;

You should now be seeing a map overlaid with lots of blue circles:

The code

See the Pen UK charging points map (Step 2) by Peter Cook (@createwithdata) on CodePen.

Wrapping up

In this part you loaded a CSV file of charging points into your application and plotted the points on the map.

D3 was able to do a lot of the work for us, in particular making the request and converting the CSV file into an array of objects. We were then able to draw a marker for each charging point using Leaflet's circleMarker.

In the next part we'll style the markers in a data-driven fashion. They'll be colour coded according to the operator name (using the deviceControllerName property) and their status (using the chargeDeviceStatus property).

Happy mapping and I hope to see you in the next part!