Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

zoom to geojson polygons bounds in Google Maps API v3

Tags:

I'm loading geojson from a Postgis-database and want to display it on my map. After drawing a polygon, I want the map to zoom to the extents of the added polygon.

My data loads fine and displays correct on the map, but I cannot figure out how to get the bounds and change the zoom to the newly added polygon. I tried to use parts of the code from Google's Data Layer: Drag and Drop GeoJSON example, but the displayed map zooms in somewhere in the Pacific Ocean close to the Baker Islands, while the polygon is displayed correctly in Luxembourg.

Here the code I am using:

window.addEventListener("load", func1);

function func1(){
  //Load mapdata via geoJson
  var parzelle = new google.maps.Data();
  parzelle.loadGeoJson("./mapdata/get_parzelle_geojson.php<?php echo  "?gid=".$_GET['gid'];?>");

  // Set the stroke width, and fill color for each polygon
  var featureStyle = {
    fillColor: '#ADFF2F',
    fillOpacity: 0.1,
    strokeColor: '#ADFF2F',
    strokeWeight: 1
  }

  parzelle.setStyle(featureStyle);
  parzelle.setMap(map);

  zoom(map);
}

function zoom(map) {
  var bounds = new google.maps.LatLngBounds();
  map.data.forEach(function(feature) {
    processPoints(feature.getGeometry(), bounds.extend, bounds);
  });
  map.fitBounds(bounds);
}

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);
    });
  }
}

Is there a way to get that to work? It seems that there is no simple method to get the bounds of polygons in google.maps.data-layers.

like image 703
geom Avatar asked Feb 13 '15 19:02

geom


2 Answers

There are issues with your posted code. You can use map.data to access the data layer.

Working code snippet. Initially zooms to all the features in the GeoJSON. Zooms to each individual polygon on click.

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

function func1() {
  map = new google.maps.Map(document.getElementById('map-canvas'), {
    zoom: 4,
    center: {
      lat: 0,
      lng: 0
    }
  });
  // Set the stroke width, and fill color for each polygon
  var featureStyle = {
    fillColor: '#ADFF2F',
    fillOpacity: 0.1,
    strokeColor: '#ADFF2F',
    strokeWeight: 1
  };

  // zoom to show all the features
  var bounds = new google.maps.LatLngBounds();
  map.data.addListener('addfeature', function(e) {
    processPoints(e.feature.getGeometry(), bounds.extend, bounds);
    map.fitBounds(bounds);
  });

  // zoom to the clicked feature
  map.data.addListener('click', function(e) {
    var bounds = new google.maps.LatLngBounds();
    processPoints(e.feature.getGeometry(), bounds.extend, bounds);
    map.fitBounds(bounds);
  });
  //Load mapdata via geoJson
  map.data.loadGeoJson('https://storage.googleapis.com/maps-devrel/google.json');
}

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,
#map-canvas {
  height: 100%;
  width: 100%;
  margin: 0px;
  padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="map-canvas" style="border: 2px solid #3872ac;"></div>
like image 102
geocodezip Avatar answered Oct 29 '22 00:10

geocodezip


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.

like image 33
pscl Avatar answered Oct 28 '22 23:10

pscl