Shapes don't respect map's 'draggable' property - javascript

Edge scrolling
Let's say I've created a simple map with default options, a draggable marker and a draggable shape (I've tested it with circle, rectangle, polygon and polyline). When I drag the marker or shape to the edge of map canvas, the map starts scrolling and that's fine.
JSFiddle demo
The problem
When I set map's draggable property to false, the edge scrolling doesn't work anymore with the marker, but all the shapes ignore it and the map is still scrolled - and that's unexpected behaviour.
var mapOptions = {
...
draggable: false
};
JSFiddle demo
The problem exists in both release (3.16) and experimental (3.17) versions. I've reported it on google's bugtracker, but it will probably take years before they fix it. So, does anyone know a workaround?
Edit: for the sake of simplicity, let's assume that zooming the map is also disabled

You will need to listen to the map zoom_changed, bounds_changed and the circle dragend events.
If the shape is dragged outside of the defined bounds, set it back to its last position and set the map center to the original value.
function initialize() {
var bounds = null;
var zoomLevel = 15;
var center = new google.maps.LatLng(20.291, 153.027);
var mapOptions = {
zoom: zoomLevel,
center: center,
mapTypeId: google.maps.MapTypeId.TERRAIN,
draggable: false
};
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var marker = new google.maps.Marker({
map: map,
position: center,
draggable: true
});
var circlePos = new google.maps.LatLng(20.281, 153.037);
var circle = new google.maps.Circle({
map: map,
center: circlePos,
radius: 100,
strokeWeight: 1,
fillColor: '#000000',
fillOpacity: 1,
draggable: true
});
google.maps.event.addListener(map, 'zoom_changed', function () {
// If user changes zoome level, get the new level and the new map bounds
zoomLevel = map.getZoom();
bounds = map.getBounds();
});
google.maps.event.addListener(map, 'bounds_changed', function () {
// Get the initial map bounds if not set yet
if (!bounds) {
bounds = map.getBounds();
}
});
google.maps.event.addListener(circle, 'dragend', function () {
var position = circle.getCenter();
if (bounds.contains(position)) {
// Update the circle position
circlePos = position;
} else {
// Set the circle back to its last position
// Reset the map center as it might have changed
circle.setCenter(circlePos);
map.setCenter(center);
}
});
};
JSFiddle demo
Kindly note that you can eliminate the zoom_changed event listener if you disable the zooming options on your map. Problem if a user can use the zoom is that your shape can still disappear from the map bounds if the user zooms in, which can be confusing.

Google fixed it in version 3.19, it now works properly.

Related

Google Maps JS API: fitBounds and maintain center [duplicate]

I've been looking around for a solution to this problem, but i can't seem to find somthing that solves this. The closest i get is this thread. But this doesn't work.
What i'm trying to do is to run fitbounds based on a set of markers which works fine. But i would also like to center the map based on the users location (the bouncing marker in the plunk) and still keep all markers within the map view.
If i try to setCenter after fitBounds, some markers are outside of the map view.
Is there some nifty way of combining these two functions?
Here's the plunk illustrating the issue.
function initialize() {
var userCenter = new google.maps.LatLng(51.508742, -0.120850);
var userCenterMarker = new google.maps.Marker({
position: userCenter
});
userCenterMarker.setAnimation(google.maps.Animation.BOUNCE);
var mapProp = {
center: userCenter,
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("googleMap"), mapProp);
var bounds = new google.maps.LatLngBounds();
var markers = getMarkers();
$(markers).each(function() {
bounds.extend(this.position);
this.setMap(map);
});
userCenterMarker.setMap(map);
map.fitBounds(bounds);
setTimeout(function() {
map.setCenter(userCenter);
}, 1500);
}
Thanks!
Simple solution: Add your "user marker" to the bounds, do fitBounds, then decrement the resulting zoom by 1 and center on that marker.
bounds.extend(userCenterMarker.getPosition());
map.fitBounds(bounds);
google.maps.event.addListenerOnce(map,'bounds_changed', function() {
map.setZoom(map.getZoom()-1);
});
working fiddle
More complex solution: Center on the "user marker", check to see if the marker bounds is completely included in the map's current bounds (map.getBounds().contains(markerBounds)), if not, decrement the zoom level by 1.
The above answer didn't work for me. Here's what did:
contained = true;
map.fitBounds(bounds);
map.setCenter(center);
newbounds = map.getBounds();
for (i = 0; i < l; i ++) {
if (!newbounds.contains(markers[i].getPosition())) {
contained = false;
}
}
if (!contained) map.setZoom(map.getZoom() - 1);

Wrong position of infowindow on small zoom levels. Google maps api v3

On small zoom levels one place will be displayed twice or more (world map is repeated horizontally). When I place marker on map with coordinates (e.g. -32.05604, 115.74718) I will see it on map more than once. It's normal.
But if I try to show infowindow on mouse hover I will get wrong behaviour. Infowindow will be always showed near one of my markers and never near other, without relation what marker was under mouse cursor.
See example here: (try to move mouse to left marker on map).
https://jsfiddle.net/m3wpk1gr/1/
How to show infowindow for marker which under mouse?
My code:
function initialize() {
var myLatLng = new google.maps.LatLng(-32.05604, 115.74718),
myOptions = {
zoom: 1,
center: new google.maps.LatLng(-32.05604, 0)
},
map = new google.maps.Map(document.getElementById('map-canvas'), myOptions),
marker = new google.maps.Marker({
position: myLatLng,
map: map
});
marker.setMap(map);
var iw = new google.maps.InfoWindow();
marker.addListener('mouseover', function() {
iw.setContent('InfoWindow');
iw.open(map, this);
});
marker.addListener('mouseout', function() {
iw.close();
});
}
initialize();
I'm afraid there is nothing you can do to get the desired result(the position is correct, so when the position exists multiple times on a map, the API has to make a decision).
What you can do: set the optimized-option of the marker to false, then they will not be repeated at lower zoom-levels

Mouseover and mouseout for rectangle are not fired correctly in Google Maps API v3

I have a map, and I draw a rectangle on it. Here is what I want: whenever my mouse enter that rectangle, open an infowindow, when my mouse leave, close the infowindow.
I have successfully created a map and drawn a rectangle. Here is my code:
var map;
function initialize() {
// Init map
var mapOptions = {
center: { lat: ***, lng: *** },
zoom: 13,
draggable: false,
scrollwheel: false,
zoomControl: false,
streetViewControl: false,
mapTypeControl: false,
disableDoubleClickZoom: true
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
google.maps.event.addListenerOnce(map, 'bounds_changed', function () {
drawGrid();
});
} // end initialize
function drawGrid() {
var rectangle = new google.maps.Rectangle({
strokeColor: '#000',
strokeWeight: 2,
fillOpacity: 0,
map: map,
bounds: new google.maps.LatLngBounds(sw1, ne1) //sw1 and ne1 is my variable
});
var infowindow = new google.maps.InfoWindow({
content: "Hello",
position: rectangle.getBounds().getCenter()
});
google.maps.event.addListener(rectangle, 'mouseover', function () {
infowindow.open(map);
});
google.maps.event.addListener(rectangle, 'mouseout', function () {
infowindow.close();
});
}
google.maps.event.addDomListener(window, 'load', initialize);
You can see the result below. The rectangle is the black one.
Now, the problems are:
Mouseover event is fired only when I let my mouse follow the green arrows.
Mouseout event is fired only when my mouse follow the green arrows (yes, from out to in, not in to out as expected), and it's fired twice.
Why do I encounter those problems? What did I do wrong? How to solve this problem? Thank you so much for your help.
There was a change to the way Firefox 39.0 handles mouse events. See issue 8278 in the issue tracker
Project Member #4 enoch...#google.com
Thanks for reporting this issue. Indeed, it appears that Firefox 39 has made changes to its mouse event, which is causing the API to behave incorrectly.
Status: Accepted
Owner: enoch...#google.com
Labels: Internal-20820906
Note that users have reported that v=3 (the release version) is working correctly and this issue only appears in v=3.exp (the "experimental" version).

Google Maps Draw -- draw line or polygon by dragging

Currently, you can draw polygons or polylines on a map by clicking, which creates a node. However, if you wanted to follow a feature such as a river or shoreline, this could be both tedious and innacurate.
Does anyone know of a way where a path could be drawn either by click-dragging the mouse, or by clicking to start, then dragging a path, then clicking to stop?
I've looked at the DrawingManager and MouseEvent, but I'm not seeing anything promising yet.
Is there a way to wire up drawing based on events such as click and mouseMove?
This would allow for much more accurate and quick features.
Possible workflow:
onmousedown on the map set the draggable-option of the map to false, create a Polyline-Instance and set the clickable-option of the Polyline to false
observe the mousemove-event of the map, each time it occurs push the returned LatLng to the path of the Polyline
onmouseup remove the mousemove-listener for the map and set the draggable-option of the map back to true. Your Polyline has been finished
When you wan't to create a Polygon, create now a Polygon-instance, set the path of the Polygon to the path of the Polyline and remove the Polyline
<edit>:
It's recommendable to draw only with a pressed right mousebutton, otherwise the map would never be draggable.
Demo: http://jsfiddle.net/doktormolle/YsQdh/
code snippet: (from linked jsfiddle)
function initialize() {
var mapOptions = {
zoom: 14,
center: new google.maps.LatLng(52.5498783, 13.425209099999961),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map_canvas'),
mapOptions);
google.maps.event.addDomListener(map.getDiv(), 'mousedown', function(e) {
//do it with the right mouse-button only
if (e.button != 2) return;
//the polygon
poly = new google.maps.Polyline({
map: map,
clickable: false
});
//move-listener
var move = google.maps.event.addListener(map, 'mousemove', function(e) {
poly.getPath().push(e.latLng);
});
//mouseup-listener
google.maps.event.addListenerOnce(map, 'mouseup', function(e) {
google.maps.event.removeListener(move);
if (document.getElementById('overlay').value == 'Polygon') {
var path = poly.getPath();
poly.setMap(null);
poly = new google.maps.Polygon({
map: map,
path: path
});
}
});
});
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body {
height: 100%;
margin: 0
}
#map_canvas {
height: 90%;
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
Use the right mouse-button to draw an overlay
<br/>
<select id="overlay">
<option value="Polyline">Polyline</option>
<option value="Polygon">Polygon</option>
</select>
<div id="map_canvas"></div>

dragend event listener not firing in Google Maps API v3?

It won't even log to the console. I'm not sure what's going on here:
var mapOptions = {
zoom: 5,
center: new google.maps.LatLng(-41.2, 173.3),
mapTypeId: google.maps.MapTypeId.ROADMAP,
streetViewControl: false
}
var homeMarker = new google.maps.Marker();
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
google.maps.event.addListener(map, "click", function(event) {
// If the marker already exists, set it's position to null
if (homeMarker) {
homeMarker.setPosition(null);
}
// Instantiate the marker again
homeMarker = new google.maps.Marker({
position: event.latLng,
map: map,
title: 'Your Home Location',
draggable: true
});
// Set the input fields to the latitude and longitude
var latitude = event.latLng.lat();
var longitude = event.latLng.lng();
$('input#homeLat').val(latitude.toFixed(6));
$('input#homeLong').val(longitude.toFixed(6));
});
// What is wrong here?
google.maps.event.addListener(homeMarker, "dragend", function(event) {
console.log('foo');
});
Basically, what is meant to happen is that I want to fetch the coordinates from the new position of the marker, which can be changed via a click on the map and a drag of the marker itself. I've got the former working, but my eventListener for dragend doesn't seem to be firing at all. Any ideas?
Alert while dragging, same code works for me.
getPosition() helps to get the current marker position
Try this,
google.maps.event.addListener(homeMarker, "dragend", function(event) {
alert('map dragged');
homeMarker.getPosition();
});

Categories