Drag and Drop GeoJSON files onto Bing Maps V8

GeoJSON is a common file format used for storing spatial data as a JSON object and is easy to import and export in Bing Maps V8 using the GeoJSON module. This file format tends to be more compact then its XML equivalents. This results in a much smaller file size, making it ideal for transferring spatial data to web and mobile applications. These files typically use a .js or .json file extensions, however occasionally you may come across some files that use .geojson. The following is an example of a GeoJSON file containing the location of New York.

 {
    "type": "FeatureCollection",
    "features": [
      {
          "type": "Feature",
          "geometry": {
              "type": "Point",
              "coordinates": [-74.006393, 40.714172]
          },
          "properties": {
              "name": "New York",
              "description": "New York"
          }
      }
    ]
}

Additional information on this file format specification can be found here.

Drag and Drop a GeoJSON file

From time to time I come across an interesting data set in GeoJSON format that I want to quickly view in Bing Maps. The Bing Maps API’s make it easily read these files, but if I just want to quickly view the data I don’t really want to write an app each time I want to view a GeoJSON file. With this in mind we will take a look at how to create a reusable app where we can simply drag and drop GeoJSON files onto the map and have them load.

To accomplish this, the HTML5 FileReader and Drag & Drop API’s will be used. Good documentation on how to use these API’s together can be found here. Our application will first need to load the map then the GeoJSON module. From there we will attach drag and drop events to the maps main DOM element. When one or more files are dropped onto the map we will loop through each of them, attempt to read them as a GeoJSON file and then add the data to the map.

 <!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
    <script type='text/javascript'>
    var map;

    function GetMap() {
        map = new Microsoft.Maps.Map('#myMap', {
            credentials: 'Your Bing Maps Key',
            zoom: 1
        });

        //Load the GeoJSON module.
        Microsoft.Maps.loadModule('Microsoft.Maps.GeoJson', function () {

            //Setup the drag & drop listeners on the map.
            var dropZone = document.getElementById('myMap');
            dropZone.addEventListener('dragover', handleDragOver, false);
            dropZone.addEventListener('drop', handleFileSelect, false);
        });
    }

    function handleDragOver(evt) {
        //Stop the browser from performing its default behavior when a file is dragged and dropped.
        evt.stopPropagation();
        evt.preventDefault();

        evt.dataTransfer.dropEffect = 'copy';
    }

    function handleFileSelect(evt) {
        //Stop the browser from performing its default behavior when a file is dragged and dropped.
        evt.stopPropagation();
        evt.preventDefault();

        //Remove any existing data from the map.
        map.entities.clear();

        //The list of files that have been dragged and dropped onto the map.
        var files = evt.dataTransfer.files; 

        //Keep track of the bounding box of all the data from all files dropped into the map.
        var dataBounds = null;

        //Loop through and attempt to read each file. 
        for (var i = 0; i < files.length; i++) {
            var reader = new FileReader();

            reader.onload = function (e) {
                try {
                    var geoJsonText = e.target.result;

                    //Attempt to parse the file as GeoJSON and add the shapes to the map.
                    var shapes = Microsoft.Maps.GeoJson.read(geoJsonText);
                    map.entities.push(shapes);
                    
                    //Calculate the bounding box of the data in the single file. 
                    var bounds = Microsoft.Maps.LocationRect.fromShapes(shapes);

                    //If data is already loaded from another GeoJSON file, merge the bounding boxes together.
                    if (dataBounds) {
                        dataBounds = Microsoft.Maps.LocationRect.merge(dataBounds, bounds);
                    } else {
                        dataBounds = bounds;
                    }

                    //Update the map view to show the data.
                    map.setView({ bounds: dataBounds, padding: 50 });
                } catch (e) {
                    alert('Unable to read file as GeoJSON.');
                }
            };

            //Read the file as text.
            reader.readAsText(files[i]);
        }
    }
    </script>
    <script type='text/javascript' src='https://www.bing.com/api/maps/mapcontrol?callback=GetMap' async defer></script>
</head>
<body>
    <div id="myMap" style="position:relative;width:800px;height:600px;"></div>
</body>
</html>

The following image shows the neighborhood boundaries of Los Angeles that came from a GeoJSON file that was downloaded from the Los Angeles Times Boundary API.

 

Try it now

Additional Resources