Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google maps drag rectangle to select markers

I am trying to draw a rectangle on the google map and detect if any markers are within the bounds of the rectangle.

To draw a rectangle you hold shift key, click and drag.

I have a working sample here - http://jsfiddle.net/dbwPQ/3/

Why does the .contains method only return true if the rectangle is drawn from bottom left to top right or top right to bottom left.

And yet the same area drawn from top left to bottom right or bottom right to top left returns false????

                if (boundsSelectionArea.contains(markers[key].position))
            //if (gribBoundingBox.getBounds().getNorthEast().lat() <= markers[key].position.lat() &&
            //    gribBoundingBox.getBounds().getSouthWest().lat() >= markers[key].position.lat() && 
            //    gribBoundingBox.getBounds().getSouthWest().lng() <= markers[key].position.lng() && 
            //    gribBoundingBox.getBounds().getNorthEast().lng() >= markers[key].position.lng() ) 
            {
                //if(flashMovie !== null && flashMovie !== undefined) {
                console.log("User selected:" + key + ", id:" + markers[key].id);
                //}
            } else {
                //if(flashMovie !== null && flashMovie !== undefined) {
                console.log("User NOT selected:" + key + ", id:" + markers[key].id);
                //} 
            }

UPDATE this works but i dont know why? http://jsfiddle.net/dbwPQ/4/

like image 325
Vince Lowe Avatar asked Jul 16 '13 10:07

Vince Lowe


People also ask

How do I move a marker smoothly on Google Maps?

initialize() function creates a google Map with location Marker. transition() & moveMarker() are used to move location marker smoothly on Google Map.

How do you drag and drop a red marker on a map?

This is done by placing your cursor over the red marker, left click and hold the mouse button down. This captures the marker and allows you to move it to the right position on the map.


3 Answers

It looks like the google.maps.Rectangle.getBounds is returning "invalid" bounds

key:Vince posn:(53.801279, -1.5485670000000482) out of bnds:((55.45394132943307, -4.0869140625), (52.72298552457069, 1.7138671875))
key:Vince posn:(53.801279, -1.5485670000000482) in bnds:((52.26815737376817, -4.04296875), (55.65279803318956, 2.2412109375))

If you extend an empty google.maps.LatLng object with your two corners, it will work:

google.maps.event.addListener(themap, 'mousemove', function (e) {
    if (mouseIsDown && shiftPressed) {
        if (gribBoundingBox !== null) // box exists
        {
            bounds.extend(e.latLng);                
            gribBoundingBox.setBounds(bounds); // If this statement is enabled, I lose mouseUp events

        } else // create bounding box
        {
            bounds = new google.maps.LatLngBounds();
            bounds.extend(e.latLng);
            gribBoundingBox = new google.maps.Rectangle({
                map: themap,
                bounds: bounds,
                fillOpacity: 0.15,
                strokeWeight: 0.9,
                clickable: false
            });
        }
    }
});

working example

code snippet:

var map;
var markers = {};
var bounds = null;
// add marker to object
var posi = new google.maps.LatLng(53.801279, -1.548567);
var name = 'Vince';
markers[name] = {};
markers[name].id = 1;
markers[name].lat = 53.801279;
markers[name].lng = -1.548567;
markers[name].state = 'Online';
markers[name].position = posi;
markers[name].selected = false;

$(document).ready(function() {

  var mapOptions = {
    zoom: 5,
    center: new google.maps.LatLng(53.801279, -1.548567),
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };
  map = new google.maps.Map(document.getElementById('map'), mapOptions);
  var infowindow = new google.maps.InfoWindow();
  for (var key in markers) {
    var marker = new google.maps.Marker({
      position: new google.maps.LatLng(markers[key].lat, markers[key].lng),
      map: map
    });
    markers[key].marker = marker;

    google.maps.event.addListener(marker, 'click', (function(marker, key) {
      return function() {
        infowindow.setContent(key);
        infowindow.open(map, marker);
      }
    })(marker, key));
  }

  // Start drag rectangle to select markers !!!!!!!!!!!!!!!!
  var shiftPressed = false;

  $(window).keydown(function(evt) {
    if (evt.which === 16) { // shift
      shiftPressed = true;
    }
  }).keyup(function(evt) {
    if (evt.which === 16) { // shift
      shiftPressed = false;
    }
  });

  var mouseDownPos, gribBoundingBox = null,
    mouseIsDown = 0;
  var themap = map;

  google.maps.event.addListener(themap, 'mousemove', function(e) {
    if (mouseIsDown && shiftPressed) {
      if (gribBoundingBox !== null) // box exists
      {
        bounds.extend(e.latLng);
        gribBoundingBox.setBounds(bounds); // If this statement is enabled, I lose mouseUp events

      } else // create bounding box
      {
        bounds = new google.maps.LatLngBounds();
        bounds.extend(e.latLng);
        gribBoundingBox = new google.maps.Rectangle({
          map: themap,
          bounds: bounds,
          fillOpacity: 0.15,
          strokeWeight: 0.9,
          clickable: false
        });
      }
    }
  });

  google.maps.event.addListener(themap, 'mousedown', function(e) {
    if (shiftPressed) {

      mouseIsDown = 1;
      mouseDownPos = e.latLng;
      themap.setOptions({
        draggable: false
      });
    }
  });

  google.maps.event.addListener(themap, 'mouseup', function(e) {
    if (mouseIsDown && shiftPressed) {
      mouseIsDown = 0;
      if (gribBoundingBox !== null) // box exists
      {
        var boundsSelectionArea = new google.maps.LatLngBounds(gribBoundingBox.getBounds().getSouthWest(), gribBoundingBox.getBounds().getNorthEast());

        for (var key in markers) { // looping through my Markers Collection 

          //                    if (boundsSelectionArea.contains(markers[key].marker.getPosition())) 
          if (gribBoundingBox.getBounds().contains(markers[key].marker.getPosition())) {
            //if(flashMovie !== null && flashMovie !== undefined) {
            markers[key].marker.setIcon("http://maps.google.com/mapfiles/ms/icons/blue.png")
            document.getElementById('info').innerHTML += "key:" + key + " posn:" + markers[key].marker.getPosition() + " in bnds:" + gribBoundingBox.getBounds() + "<br>";
            // console.log("User selected:" + key + ", id:" + markers[key].id);
            //}   
          } else {
            //if(flashMovie !== null && flashMovie !== undefined) {
            markers[key].marker.setIcon("http://maps.google.com/mapfiles/ms/icons/red.png")
            document.getElementById('info').innerHTML += "key:" + key + " posn:" + markers[key].marker.getPosition() + " out of bnds:" + gribBoundingBox.getBounds() + "<br>";
            // console.log("User NOT selected:" + key + ", id:" + markers[key].id);
            //} 
          }
        }

        gribBoundingBox.setMap(null); // remove the rectangle
      }
      gribBoundingBox = null;

    }

    themap.setOptions({
      draggable: true
    });
    //stopDraw(e);
  });

});
#map {
  height: 500px;
  width: 500px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="map"></div>
<div id="info"></div>
like image 163
geocodezip Avatar answered Oct 01 '22 21:10

geocodezip


I have some change base on geocodezip's working version.

If you use "extend" of LatLngBounds, it will be only getting bigger but not smaller when you move inside. So I generate LatLngBounds every mouse move to fit my requirement. (It might be optimized in another way I guess.)

Update: Found another issue, if user released the shift key before mouse up, the gridbound will stick on the map, fixed it in the following code.

google.maps.event.addListener(themap, 'mousemove', function (e) {
+   if (mouseIsDown && (shiftPressed|| gribBoundingBox != null) ) {
        if (gribBoundingBox !== null) // box exists
        {         
+           var newbounds = new google.maps.LatLngBounds(mouseDownPos,null);
+           newbounds.extend(e.latLng);    
+           gribBoundingBox.setBounds(newbounds); // If this statement is enabled, I lose mouseUp events

        } else // create bounding box
        {
            gribBoundingBox = new google.maps.Rectangle({
                map: themap,
+               bounds: null,
                fillOpacity: 0.15,
                strokeWeight: 0.9,
                clickable: false
            });
        }
    }
});

google.maps.event.addListener(themap, 'mouseup', function (e) {
+   if (mouseIsDown && (shiftPressed|| gribBoundingBox != null)) {
        mouseIsDown = 0;

    /*........*/
  • Working fiddle http://jsfiddle.net/7ZxMA/4/
  • demo http://fiddle.jshell.net/7ZxMA/4/show/

Update: Found another scenario that you might interested.

use a button to select map. (User could click the "select map" button to select markers or use shift key to select markers.)

  • working fiddle http://jsfiddle.net/7ZxMA/6/
  • demo http://fiddle.jshell.net/7ZxMA/6/show/
like image 25
TonyQ Avatar answered Oct 01 '22 23:10

TonyQ


You missuse constructor of the google.maps.LatLngBounds class. According to documentation you must pass two arguments: south-west and north-east corners. However, sometimes you pass south-east and north-west corners. This probably has impact on .contains method.

like image 35
gawi Avatar answered Oct 01 '22 21:10

gawi