3

I'm having troubles centering and zooming on the information in the data layer. I have tried to use the approach suggested here: stackoverflow question: zoom to geojson polygons bounds in Google Maps API v3. I still initially zoom into the same spot that he was, some where in the pacific ocean near baker island. I am loading a GeoJson object from the server and it displays correctly. My code:

function loadMap () {
    var m = document.getElementById("googleMap");
    var mapProp = { 
        disableDoubleClickZoom: true, 
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    var map = new google.maps.Map(m, mapProp);

    map.data.addListener('addfeature', function(e) {            
        var bounds = new google.maps.LatLngBounds();
        processPoints(e.feature.getGeometry(), bounds.extend, bounds);

        map.setCenter(bounds.getCenter());
        map.fitBounds(bounds);
    });

    var geoJsonObject = {
        type: "FeatureCollection",
        features: [
           {
              type: "Feature",
              properties: {},
              geometry: {
                  type: "MultiPolygon",
                  coordinates: [
                      [[[-86.80795499999999, 36.146389], [-86.80605800006222, 36.14733499995285], [-86.806471, 36.147928], [-86.80836699994975, 36.14697700000941], [-86.80795499999999, 36.146389]]],
                      [[[-86.803842, 36.143921999999996], [-86.803761, 36.144005], [-86.80374600001942, 36.1441770000485], [-86.804918, 36.1458], [-86.805436, 36.145536], [-86.80621699999999, 36.146585], [-86.80755499999131, 36.145895000035935], [-86.807208, 36.145385999999995], [-86.806328, 36.144205], [-86.803842, 36.143921999999996]]]
                  ]
              }
           }
        ]
    };
    map.data.addGeoJson(geoJsonObject);
}

function processPoints(geometry, callback, thisArg) {
    if(geometry instanceof google.maps.LatLng) {
        callback.call(thisArg, geometry);
    }
}

Are there any other suggestions?

Community
  • 1
  • 1
adam
  • 502
  • 1
  • 6
  • 17
  • What does _your_ geoJSON data look like? Can you provide a [Minimal, Complete, Tested and Readable example](http://stackoverflow.com/help/mcve) that demonstrates the problem? – geocodezip Sep 16 '15 at 17:48
  • I've just edited to include a mock out of the object returned from the server. The polygons get much more complicated than this so I choose a small one. This is the area around a few block in Nashville, TN. – adam Sep 16 '15 at 18:08

3 Answers3

7

Your modified processPoints routine doesn't handle polygons.

Yours:

function processPoints(geometry, callback, thisArg) {
    if(geometry instanceof google.maps.LatLng) {
        callback.call(thisArg, geometry);
    }
}

From the referenced answer on SO:

function processPoints(geometry, callback, thisArg) {
    if (geometry instanceof google.maps.LatLng) {
        callback.call(thisArg, geometry);
    } else if (geometry instanceof google.maps.Data.Point) {
        callback.call(thisArg, geometry.get());
    } else {
        geometry.getArray().forEach(function (g) {
            processPoints(g, callback, thisArg);
        });
    }
}

working code snippet:

window.addEventListener("load", loadMap);
var map;

function loadMap() {
  var m = document.getElementById("googleMap");
  var mapProp = {
    disableDoubleClickZoom: true,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };
  var map = new google.maps.Map(m, mapProp);
  var bounds = new google.maps.LatLngBounds();
  map.data.addListener('addfeature', function(e) {
    processPoints(e.feature.getGeometry(), bounds.extend, bounds);
    map.setCenter(bounds.getCenter());
    map.fitBounds(bounds);
  });

  var geoJsonObject = {
    type: "FeatureCollection",
    features: [{
      type: "Feature",
      properties: {},
      geometry: {
        type: "MultiPolygon",
        coordinates: [
          [
            [
              [-86.80795499999999, 36.146389],
              [-86.80605800006222, 36.14733499995285],
              [-86.806471, 36.147928],
              [-86.80836699994975, 36.14697700000941],
              [-86.80795499999999, 36.146389]
            ]
          ],
          [
            [
              [-86.803842, 36.143921999999996],
              [-86.803761, 36.144005],
              [-86.80374600001942, 36.1441770000485],
              [-86.804918, 36.1458],
              [-86.805436, 36.145536],
              [-86.80621699999999, 36.146585],
              [-86.80755499999131, 36.145895000035935],
              [-86.807208, 36.145385999999995],
              [-86.806328, 36.144205],
              [-86.803842, 36.143921999999996]
            ]
          ]
        ]
      }
    }, {
      type: "Feature",
      properties: {},
      geometry: {
        type: "MultiPolygon",
        coordinates: [
          [
            [
              [-86.82083, 36.148815],
              [-86.820293, 36.149196],
              [-86.819585, 36.148572],
              [-86.819971, 36.148087],
              [-86.82083, 36.148815]
            ]
          ]
        ]
      }
    }]
  };
  map.data.addGeoJson(geoJsonObject);
}

function processPoints(geometry, callback, thisArg) {
  if (geometry instanceof google.maps.LatLng) {
    callback.call(thisArg, geometry);
  } else if (geometry instanceof google.maps.Data.Point) {
    callback.call(thisArg, geometry.get());
  } else {
    geometry.getArray().forEach(function(g) {
      processPoints(g, callback, thisArg);
    });
  }
}
html,
body,
#googleMap {
  height: 100%;
  width: 100%;
  margin: 0px;
  padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="googleMap"></div>
Community
  • 1
  • 1
geocodezip
  • 158,664
  • 13
  • 220
  • 245
  • 1
    I would up vote your answer if I had enough reputation. Thank you very much! – adam Sep 16 '15 at 18:38
  • I would upvote this, but the addfeature event triggers on multiple features, so you're basically resetting the LatLngBounds constructor each time a feature is added, and therefore you can't extend the bounds through each iteration. – cj5 May 06 '16 at 18:03
  • updated to include all the polygons in the GeoJSON (so works for more than the last polygon) – geocodezip May 06 '16 at 23:16
4

See my answer here. https://stackoverflow.com/a/42127338/1628461

The recursive processing function suggested above is clever but there is no need to handle the various Geometry types manually.

The Maps API (at least as of V3.26 today) supports Data.Geometry.prototype.forEachLatLng() which abstracts away the various Geometry types.

Given that you have already imported your geoJSON into map.data, it is easy to rezoom the map to fit ("fit-to-bounds"):

var bounds = new google.maps.LatLngBounds(); 
map.data.forEach(function(feature){
  feature.getGeometry().forEachLatLng(function(latlng){
     bounds.extend(latlng);
  });
});

map.fitBounds(bounds);

If your features are already being iterated for another reason (e.g. setting styles), you can work this code into your existing loop for efficiency.

pscl
  • 3,322
  • 25
  • 29
0

@geocodezip's answer doesn't work for me. As the addfeature event will trigger for every feature in the JSON. What the this answer shows us is that it will reset the LatLngBounds() instance, therefore resetting the extension of the bounding box.

I am doing this using an additional javascript library called d3.js (very very handy library btw), which supplies a geo class that can read through GeoJSON and generate the bounding box coordinates needed for the Google map instance's fitBounds() method.

myNamespace.getLogs().then(function (resp) {
    var logData = myNamespace.map.data.addGeoJson(resp);
    var jsonBounds = d3.geo.bounds(resp);
    myNamespace.mapBounds = new google.maps.LatLngBounds({
        lat: jsonBounds[0][1],
        lng: jsonBounds[0][0]
    }, {
        lat: jsonBounds[1][1],
        lng: jsonBounds[1][0]
    });
    myNamespace.map.fitBounds(myNamespace.mapBounds);
});

This produces an array of a pair array items, one for SW and one for NE. For example:

Array([Array([sw_lng, sw_lat]), Array([ne_lng, ne_lat])])
cj5
  • 785
  • 3
  • 12
  • 34