Search code examples
google-mapsgeojson

Google maps check if current bounds are inside the bounds of a data layer


I am loading a data layer in a google map, over a certain country (it's a drawing over a country):

map.data.addGeoJson(geoJsonObject);

I am pretty sure there isn't, but... is there a way to check that the bounds of the map are inside the bounds of the data layer?

(basically, I want to know, when the user navigates on the map, if the current viewport is inside data layer);

var bounds = this.map.getBounds();
var sw = bounds.getSouthWest();

Maybe I can query the data layer in the position of the south west bound and check for some props. indicating that I am inside that data layer?

Or at least:

Does anyone know a way how to get a certain feature object programmatically, knowing the lat and long?

Here the google maps uses events to get to the feature object:

 map.data.addListener('click', function(event) {
    event.feature.setProperty('isColorful', true);
  });

But I do not want to use events. Is there a method to supply the coordinates of a point and get to the feature object? Something like:

map.getFeature(lat, long).setProperty('isColorful', true);

Solution

  • google.maps.LatLngBounds.contains function could be utilized for that purpose, but since it accepts a single location, the following solution is suggested:

    1) initialize data layer bounds from GeoJSON coordinates:

    var dataLayer = map.data;
    var layerBounds = new google.maps.LatLngBounds();
    //1.collect all coordinates from data layer
    dataLayer.forEach(function(f) {
        var geometry = f.getGeometry();
        processCoordinates(geometry, layerBounds.extend, layerBounds);
    });
    

    2) determine whether map bounds are within a layer bounds:

    if (layerBounds.contains(map.getBounds().getNorthEast()) && layerBounds.contains(map.getBounds().getSouthWest())) {
      //...   
    }
    

    Working example

    In the provided example green colored area will be displayed if map bounds are within a layer bounds, and the red colored in the opposite case:

    var area;
    function initMap() {
        var map = new google.maps.Map(document.getElementById('map'), {
            center: {
                lat: 53.349248,
                lng: -6.255323
            },
            zoom: 6,
            mapTypeId: google.maps.MapTypeId.TERRAIN
        });
    
        displayDataLayer(map);
    
        document.getElementById("btnShow").onclick = function() {
            var result = displayDataLayerBoundsArea(map);
        };
    }
    
    
    function displayDataLayer(map) {
        var dataLayer = map.data;
        dataLayer.loadGeoJson('https://gist.githubusercontent.com/vgrem/440708612b574764c309/raw/2a4e2feadc204806440c51a14c2ef1f54f4fc3d8/Census2011_Province_generalised20m.json');
        dataLayer.setMap(map);
    }
    
    function displayDataLayerBoundsArea(map) {
        var dataLayer = map.data;
        var layerBounds = new google.maps.LatLngBounds();
        //1.collect all coordinates from data layer
        dataLayer.forEach(function(f) {
            var geometry = f.getGeometry();
            processCoordinates(geometry, layerBounds.extend, layerBounds);
        });
    
        if (area != null) {
            area.setMap(null);
        }
    
        //2.determine whether map bounds are contained within a layer bounds
        if (layerBounds.contains(map.getBounds().getNorthEast()) && layerBounds.contains(map.getBounds().getSouthWest())) {
            //map.fitBounds(bounds);
            area = new google.maps.Rectangle({
                strokeColor: '#00FF00',
                strokeOpacity: 0.8,
                strokeWeight: 2,
                fillColor: '#00FF00',
                fillOpacity: 0.35,
                map: map,
                bounds: {
                    north: layerBounds.getNorthEast().lat(),
                    south: layerBounds.getSouthWest().lat(),
                    east: layerBounds.getNorthEast().lng(),
                    west: layerBounds.getSouthWest().lng()
                }
            });
        } else {
            //map.fitBounds(bounds);
            area = new google.maps.Rectangle({
                strokeColor: '#FF0000',
                strokeOpacity: 0.8,
                strokeWeight: 2,
                fillColor: '#FF0000',
                fillOpacity: 0.35,
                map: map,
                bounds: {
                    north: layerBounds.getNorthEast().lat(),
                    south: layerBounds.getSouthWest().lat(),
                    east: layerBounds.getNorthEast().lng(),
                    west: layerBounds.getSouthWest().lng()
                }
            });
        }
    }
    
    
    function processCoordinates(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) {
                processCoordinates(g, callback, thisArg);
            });
        }
    }
    #map {
       width: 800px;
       height: 640px;
    }
    <button id="btnShow">Show</button>
    <div id="map"></div>
    <script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap"></script>

    JSFiddle