Autocomplete polygons while drawing with drawingManager using the Google Maps API v3 - google-maps-api-3

I have a basic Google Map, with a drawingManager, like this:
var mapOptions = {
center: centroid,
zoom: 14,
scrollwheel: false,
mapTypeId: google.maps.MapTypeId.HYBRID,
mapTypeControlOptions: {
mapTypeIds: [google.maps.MapTypeId.HYBRID, google.maps.MapTypeId.ROADMAP]
}
}
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
var drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.POLYGON,
drawingControl: false,
polygonOptions: {
clickable: true,
draggable: true,
editable: true,
fillColor: '#ffff00',
fillOpacity: 0.8,
strokeWeight: 5
}
});
drawingManager.setMap(map);
Drawing polygons on the map works like a charm, except for one little thing. I have to explicitly close my polygon, either by clicking the first point, or by double clicking somewhere (or at least, I can't find another way). But I would like for my polygon to be closed at all times while drawing, a bit like this:
http://www.birdtheme.org/useful/v3tool.html
(select 'polygon' in the first select box next to the title).
Now I know this example doesn't use the drawingManager, but creates the polygon by hand, but I am wondering if something similar is possible using the drawingManager. I'm afraid there isn't, since I can't seem to find any reference to it in the manual, but that also kind of surprised about that, since I would think it is something that more people would like to have.

You could just make it yourself; you can easily register the click events.
google.maps.event.addListener(map, 'click', addLatLng);
poly = new google.maps.POLYGON(polyOptions);
poly.setMap(map);
function addLatLng(event) {
path = poly.getPath();
path.push(event.latLng);
}
Because you know the latlng of every point in you're polygon; you can just draw it.
You'll have to redraw it every time a new point is added.

Related

Leaflet polyline not moving on drag/zoom

I'm using leaflet with custom CRS.Simple projection. If I draw a polyline at the page Load it is more or less drawn ok (Although much more accurate in firefox than in chrome) but if I drag the map the polyline remains in the same place of the browser window, so then appears shifted respect of the background map.
Example:
Initial load
After drag the map, the map moves but the polyline remains in the same place
To add the polyline I'm converting the coordinates to the CRS.Simple projection. I don't think there is a problem here as every other map marker or text appears correctly
.....
//initialize leaflet map
map = L.map('map', {
maxZoom: mapMaxZoom,
minZoom: mapMinZoom,
zoomControl: false,
crs: L.CRS.Simple //simple coordinates system
}).setView([0, 0], mapMaxZoom);
//set the bounds of the map to the current dimension
var mapBounds = new L.LatLngBounds(
map.unproject([0, mapHeight], mapMaxZoom),
map.unproject([mapWidth, 0], mapMaxZoom)
);
//load the tiles
map.fitBounds(mapBounds);
L.tileLayer(mapData.info.tiles+'/{z}/{x}/{y}.png', {
minZoom: mapMinZoom,
maxZoom: mapMaxZoom,
bounds: mapBounds,
attribution: '',
noWrap: true,
continuousWorld: true
}).addTo(map);
.....
var pointList = [getMapCoordinates(1750,1750),
getMapCoordinates(1520,1764),
getMapCoordinates(1300,1560),
getMapCoordinates(1132,1258),
getMapCoordinates(1132,1060),
getMapCoordinates(926,960)];
polyline = new L.Polyline(pointList, {
color: 'red',
weight: 3,
opacity: 0.5,
smoothFactor: 1
});
polyline.addTo(map);
....
function getMapCoordinates(px,py)
{
//as we use simple system, transform the point (based on pixel) on map coordinates that leaflet understand
return map.unproject([px, py], map.getMaxZoom());
}
Any idea what I'm doing wrong, or is it a bug? Any workaround would be appreciated
Ok, it seems the problem was in stable version (0.7.3) Using dev version (1.0-dev) works ok and even solves the problem with the different browser drawing

How do I change the Google Maps draggable property for the map (not the marker)?

In the Google Maps v3 reference, I see there is a method setDraggable(boolean) which can be applied to a map marker.
However, I want to set setDraggable to true on the map, not on a map marker.
I have set the property draggable to false in the mapOptions, but I don't know how to set this to true later... map.setDraggable(true) does not work:
// object literal for map options
var myOptions =
{
center: new google.maps.LatLng(37.09024, -95.712891),
zoom: 4, // smaller number --> zoom out
mapTypeId: google.maps.MapTypeId.TERRAIN,
// removing all map controls
disableDefaultUI: true,
// prevents map from being dragged
draggable: false,
// disabling all keyboard shortcuts
keyboardShortcuts: false,
disableDoubleClickZoom: true,
// do not clear the map div
noClear: true
};
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
map.setDraggable(true); // does NOT work!
Try:
map.setOptions({draggable: true});
I entered my code in this section and it worked on mobile and desktop
function initialize()
{
var mapProp = {
center:myCenter,
zoom:5,
draggable:false,
mapTypeId:google.maps.MapTypeId.ROADMAP
};
setDraggable is not used in the Map class.
It is used in the:
Marker Class,
Polyline class,
Polygon class,
Rectangle class and in the Circle class.
In your case you can simply use:
map.draggable = true;

Google Map API v3 Infowindow doesn't show up on mouseover/click on a polygon

I am trying to display dynamic data in infowindows whenever user hovers over polygons on the map. Debugging shows the data and other infowindow/polygon settings are all right. I am able to get the color change on mouseover, just that infowindows doesn't show up. What might be the reason behind it? What am I missing here?
statePolygon = new google.maps.Polygon({
paths: stateBorderCoords,
strokeColor: '#f33f00',
strokeOpacity: 1,
strokeWeight: 1,
fillColor: '#ff0000',
fillOpacity: 0.2
});
statePolygon.pId = infoText; // Fetching from a JSON response
statePolygon.wPet = wPet; // Fetching from a JSON response
statePolygon.infoWindow = new google.maps.InfoWindow();
google.maps.event.addListener(statePolygon,"mouseover",function(event){
this.setOptions({fillColor: "#00FF00"});
this.infoWindow.setPosition(event.latLng);
this.infoWindow.setContent(this.wPet);
this.infoWindow.open(map, this);
});
google.maps.event.addListener(statePolygon,"mouseout",function(){
this.setOptions({fillColor: "#FF0000"});
this.infoWindow.close();
});
google.maps.event.addListener(statePolygon, 'click', function(){
//createInfoWindow(this.pId);
});
statePolygon.setMap(map);
What happens if you leave out the "this" in the line:
this.infoWindow.open(map, this);
?
I've been fighting with something similar over the last few days and just discovered my code works for google.maps.Markers (as in Google pins) but not for google.maps.Circles (and I guess google.maps.Polygons.)
My guess: "infoWindow.open(map, object)" which tries to anchor the InfoWindow to the object only seems to work for google.maps.Markers, not Circles, Polygons, etc. What does seem to work is "open(map)" which doesn't anchor it to anything. However the position of the infoWindow has to be explicitly set (which you are already doing).
Edit:
In my case this doesn't work (assuming global variable map)
var circle = { clickable: true,
strokeColor: "darkred",
strokeOpacity: 1,
strokeWeight: 1,
fillColor: "green",
fillOpacity: 1,
map: map,
center: new google.maps.LatLng(55.95,-3.19),
radius: 45
};
var marker1 = new google.maps.Circle(circle);
infoWindow = new google.maps.InfoWindow();
infoWindow.setContent("Hello");
inoWindow.setPosition(new google.maps.LatLng(55.95,-3.19));
infoWindow.open(map,marker1);
but this does:
var circle = { clickable: true,
strokeColor: "darkred",
strokeOpacity: 1,
strokeWeight: 1,
fillColor: "green",
fillOpacity: 1,
map: map,
center: new google.maps.LatLng(55.95,-3.19),
radius: 45
};
var marker1 = new google.maps.Circle(circle);
infoWindow = new google.maps.InfoWindow();
infoWindow.setContent("Hello");
infoWindow.setPosition(new google.maps.LatLng(55.95,-3.19));
infoWindow.open(map);
The only difference is in the last line.
Thinking about the above post, setting the position after opening presumably overwrites the anchor position and thus makes it appear.
First you open the InfoWindow, then set its position:
http://jsfiddle.net/fuDfa/
google.maps.event.addListener(statePolygon,"mouseover",function(event){
this.setOptions({fillColor: "#00FF00"});
this.infoWindow.setContent(this.wPet);
this.infoWindow.open(map);
this.infoWindow.setPosition(event.latLng);
});
However, I realized that if the mouse moves on top of the InfoWindow (even if it's on top of the polygon), it will count as if the mouse moved outside the polygon. So, the polygon will turn red and Infowindow will close. But since the mouse is still inside the polygon, the infowindow will open again, causing a flicker.
I don't know a way to get around this (tried a timeout but it's not reliable either). I only thought about putting the Infowindow in a preset position instead of event.latLng.

Disable dragging Google Maps while in drawing mode

I'm trying to make a page where people can draw a line over a fixed region so I want to stop the map from being panned,dragged, zoomed or moved in anyway. I've set everything I can find to false and it works fine in normal viewing mode, but when the user starts drawing using the Drawing Manager the scroll-to-zoom comes back as well as the click-to-drag. My first thought is that this is a bug/oversight in Google's code, but I'm hoping someone has a work around.
var myOptions = {
center: new google.maps.LatLng(-25,177.5),
zoom: 3,
mapTypeId: google.maps.MapTypeId.SATELLITE,
streetViewControl : false,
zoomControl: false,
disableDoubleClickZoom: true,
draggable: false,
keyboardShortcuts : false,
navigationControl : false,
scaleControl : false,
scrollwheel : false,
streetViewControl : false
};
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
update: This is the Drawing Manager code
var drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.POLYLINE,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [google.maps.drawing.OverlayType.POLYLINE]
},
polylineOptions: {
strokeWeight: 2,
strokeColor: '#ee9900',
clickable: false,
zIndex: 1,
editable: true
}
});
drawingManager.setMap(map);
I suggest you add this to the Google Maps API issue tracker
http://code.google.com/p/gmaps-api-issues/
This indeed does look like an issue with API - basically a usecase that Google didnt consider.
BUT, I highly recommend you setup a page as a demo, and include the link in the issue report.
I'm taking you at your word that this is happening, but an issue carries x100 times the weight, if there is a very easy way for others to verify (ie see it with their own eyes).
(yes, people can try and take your code to replicate it, but 1. its a lot of work, and 2. there is a high chance of inadvertantly doing something differnt and thereby side-stepping the issue)

Geofencing with Google Maps

I'm trying to let people draw a rectangle on Google Maps and store the bottomLeft and topRight coordinates.
I know I can draw a Rectangle codewise (see: http://code.google.com/intl/nl-NL/apis/maps/documentation/javascript/reference.html#Rectangle), but before i can load the bounds from my DB the people need to define it themself first off course :)
So my question is, how can I let people draw a rectangle on Google Maps (API v3) and store the coordinates of the bottomLeft and topRight corner?
Already got it to work by looking into events. Took a lot of my time to make :)
This is how i've done it for people that need it to:
function mapsInitialize()
{
startPoint = new google.maps.LatLng(lat,lon);
options = { zoom: 16, center: startPoint, mapTypeId: google.maps.MapTypeId.HYBRID};
map = new google.maps.Map(document.getElementById("map_canvas"), options);
google.maps.event.addListener(map, 'click', function(event) {
if (drawing == true){
placeMarker(event.latLng);
if (bottomLeft == null) {
bottomLeft = new google.maps.LatLng(event.latLng.Oa, event.latLng.Pa);
}
else if (topRight == null){
topRight = new google.maps.LatLng(event.latLng.Oa, event.latLng.Pa);
drawing = false;
rectangle = new google.maps.Rectangle();
var bounds = new google.maps.LatLngBounds(bottomLeft, topRight);
var rectOptions = {
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35,
map: map,
bounds: bounds
};
rectangle.setOptions(rectOptions);
}
}
});
}
function placeMarker(location) {
var marker = new google.maps.Marker({
position: location,
map: map
});
}
If I understand you properly - You need a way to get users inputting some polyline/polygon. If so - take a look at this example, where polygon is created by clicking a map. It uses some class PolygonCreator and jquery. You can adopt this method, and save result in form field (there possible a number of options: JSON or your own method of serialization)
If you just need to show that polygons on map and nothing more: you even can take advantage of geometry.encoding library and store encoded polylines into database. Or, if you are going to use spatial queries (for instance - detect if some point falls into your polygons) you better use spatial extnsion of some sort: MySQL spatial extensions, PostGIS, etc. In MySQL you can store polyline into Polyline or Polygon typed columns, which is based on OpenGIS formats.
Frankly, here on stackoverflow is a whole bunch of related information.

Resources