Tuesday, January 5, 2016

How to make a real-time updating map for your dashboard with JS

It is often useful to be able to quickly analyze events that have a geographic component. A real-time updating map that shows events that occur at certain locations on the map can be very handy for a dashboard. While it is possible to create these maps from scratch using `d3.js`, it can be useful to use some higher-level abstractions to quickly generate our maps. I'll take you through the process of creating an interactive map like this:


Check out the interactive version here


by using `DataMaps`, a library that uses `d3.js` to produce interactive maps (you can check out the library's documentation here). Rather than needing to source your geo data from scratch and process it using command line tools like `ogr2ogr` and `topojson`, then render your polygons and boundaries, and ultimately add labels and locations to your map, I'll to through a more agile process. In addition, we'll go ahead and query a live-updating JSON data source within our visualization script. This will allow for our data visualization to fetch the latest version of the earthquake data each time that it is rendered. 

First, let's create the HTML structure for our visualization:



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<html>
<meta charset='utf-8'>
<head>


</head>




<body>
    <div id="map_container" style="position: relative; width: 80%; max-height: 450px;"></div>
</body>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.12/d3.js" charset='utf-8'></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="http://datamaps.github.io/scripts/datamaps.world.min.js?v=1"></script>


<script>

</script>



</html>

We've created a div element onto which our script will bind SVG objects to create our map. We've also included the dependecies that we will be needing (`jQuery`, `d3.js`, `topojson` and `DataMaps`). We'll now start filling in the script tags on lines 21-23:



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$(document).ready(function() {

    d3.json("http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson",function(error,data){
        data = data.features;

      var map = new Datamap({
        scope: 'world',
        element: document.getElementById('map_container'),
        projection: 'equirectangular',
        height: 500,
        fills: {
          defaultFill: '#F1EBF4',
          lt50: 'rgba(0,244,244,0.9)',
          gt50: '#20438A',
        },
        geographyConfig: {
          highlightFillColor: '#bfdfec',
          highlightBorderColor: 'white',
        },
        bubblesConfig: {
          highlightFillColor: '#2265aa',
          highlightBorderColor: '#61b3b7',
        }
      });

     
 });
});

We wrap our entire script in a document ready function to ensure that it doesn't run until our DOM is ready.  Then, we use the `d3.json` function to read in our data from the USGS earthquake GeoJSON feed. For more information about this feed, check out their docs here. We then create a var called map which is a new `Datamap` object. This object will actually render our map based on the configurations that we pass on to it. This is great so far, but it will not include the bubbles that indicate where recent earthquakes have occurred. To do that, we'll have to add another set of functions at line 25 - 26:



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
      var bubble_array = [];

      function getBubble(lat, lon, name){
        var bubble = {
            name: name,
            latitude: lat,
            longitude: lon,
            radius: 10,
            fillKey: 'gt50',
        }
        bubble_array.push(bubble);
        return bubble;
      }

      for (var i = 0; i < data.length; i++) {
          getBubble(data[i].geometry.coordinates[1],
            data[i].geometry.coordinates[0],
            data[i].properties.title);
        }

       //bubbles, custom popup on hover template
     map.bubbles(bubble_array, {
       popupTemplate: function(geo, data) {
         return "<div class='hoverinfo'>" + data.name + "</div>";
       }
     });

Line 1: We create an array that will hold the data for the earthquake bubbles that we will add to the map.
Lines 3-13: We create a function that creats a bubble object with the attributes that we will be needing in order to place these on the map. This includes the latitude and longitude, which our `dataMap` object will use to plot the bubbles in their correct location when we pass the array to `map.bubbles()`.
Lines 15-19: We iterate through our data set, calling the `getBubble` function at each data point. This pushes a `bubble` item onto our array with the correct data for each point.
Lines 22-26: We finally pass the `bubble_array` to `map.bubbles`. We also go ahead and specify the `popupTemplate` var, which tells our map what to render when we hover over.

And we're done! You can see the full code snippet on Github here and the live example here.


No comments:

Post a Comment

Sign up to receive data viz talk tips and updates via email. We're low traffic and take privacy very seriously.