Snap to nearest street - google-maps

You guys have been helping out solving some of my problems with a Google Map lately, and thank you for that.
I am almost done with this - only one problem is left. When I place the first marker on the map, it snaps to the nearest street (which is fine!) but when I drag the first marker to another place, directions suddenly mess up. And the markers get mixes.
You can see an example on http://dev.korebogen.dk/gmap/
I need to make it possible to move the first marker (still snapping) and when I place the second marker, the directions first load. But in order to make the first marker snap again, I have to load the directions.
I hope some of you have a solution. Thanks in advance.

Blackpool Community Church Javascript Team has an excellent example of exactly this (direct link to the fourth example). Check out their other examples as well.
(disclaimer: I'm not affiliated with them, but have learned a lot about GMaps from their examples)
Edit:
I suspect the map events fire somewhat like this (pseudocode, for real event names etc. check the GMaps docs):
map click: mousedown, mouseup, click:{set red marker}
drag red marker: mousedown, dragstart{red marker}, mouseup, click:{set marker b} (mousedown+mouseup), dragend
both markers are set? Yes, get directions
What I'd suggest: in red-marker and marker-A dragstart functions, set some flag "dragging a marker", reset it in dragend function; in the Set marker B function, only set marker if we're currently NOT dragging something (flag is not set).

The code I gave you previously listened for the first two clicks, and added a marker for each. The problem is that when you drag the first marker, it's calling the "click" event again - and thus adding another marker at the same location.
Fortunately, the click event lets you know whether an overlay was clicked. So only execute the code that adds a new marker if overlay is null. Note that overlay is not a boolean.
var listener = GEvent.addListener(map, "click", function(overlay, latlng) {
if (overlay == null) {
// code to add new marker
}
});

Related

Marker clusterer bug when dragging the map? (Many markers on google maps)

I got the many markers solution on my website.
I noticed though that when I drag the map there seams to be an issue if I start dragging the map when holding the mouse over a many-markers icon.
The map zooms in on the position when I release the mouse button. This feature is suppose to be there when I click an icon.. but should´nt be there when I´m trying to drag the map?
It even looks like googles (own?) example has this issue so it might not be my code.
http://gmaps-samples-v3.googlecode.com/svn/trunk/toomanymarkers/toomanymarkers.html
Open the link
Check the "Many markers" box
Try to drag the map when the mouse is over a "many marker" icon.
Frustrating when the map zooms in when I try to scroll the map sideways.
google.maps.event.addListener(map,'dragstart',function(){
mc.zoomOnClick_=false;});
google.maps.event.addListener(map,'mouseup',function(){setTimeout(function(){
mc.zoomOnClick_=true;},50);});
These lines(mc is the MarkerClusterer-Instance) should help.
It disables the zoomOnClick-feature when you start dragging the map and re-enables it on mouseup(with a short delay, because mouseup fires before click)
I think this is a side effect of the intended functionality. The library will be detecting the mouseup event and zooming on the marker that was selected by mousedown I imagine.
I suppose the two options that you have are to either disable the zoom on click functionality entirely, or to alter the library yourself (possibly branch it if you think others will use it) to perhaps zoom on a different event, e.g. mousedown.
The answer from #Dr.Molle will work as long as sources are not minified (mangled names). I had to upgrade to MarkerClustererPlus which provides a method for changing zoom on click. MarkerClustererPlus ist mostly backwards compatible to MarkerClusterer.
google.maps.event.addListener(map, 'dragstart', function() {
mc.setZoomOnClick(false);
});
google.maps.event.addListener(map,'mouseup',function() {
setTimeout(function() {
mc.setZoomOnClick(true);
}, 50);
});

Positioning a draggable map marker at top-left of map window

I have a Google map that I am using to allow people to suggest locations. Currently I position a draggable marker in the centre of the map using a LatLng created with
myPosition = frmMap.getCenter();
What I would like to do though is place it initially somewhere to the edge of the map, perhaps directly under the zoom control (not unlike the way you see the yellow street view man above the zoom control).
I've searched for a solution but am not coming up with anything. My only idea was to do some maths based on the Center and NortEast but I'd rather have an absolute position based on pixels if that's possible?
As I mentioned in the comments, computing a latlng value for a marker to position under the zoom controls is not only cumbersome, but might not be feasible if the user starts panning/zooming around in the map (as the marker will move wherever the latlng takes it).
My suggestion would be to use the Drawing Library provided by the Maps API. This basically gives you a drawing control, to add markers to the map (other overlays are possible too: cirlce, polygon, polyline, rectangle). And like any control google maps provides, you can strictly position them anywhere you'd like - by setting it in the options. The snippet below describes how you initialize the drawing library:
var drawingManager = new google.maps.drawing.DrawingManager({
drawingControlOptions: {
position: google.maps.ControlPosition.LEFT_BOTTOM,
drawingModes: [
google.maps.drawing.OverlayType.MARKER
]
}
});
drawingManager.setMap(map);
This gives you your drawing control, with the mode for Marker enabled, and binds it to your map object.
You can then listen to when a marker's been added by adding a listener on the drawingManager variable for the markercomplete event. Then in the call back you can get the position of the added marker, the snippet below demonstrates this:
google.maps.event.addListener(drawingManager, 'markercomplete', function (marker) {
var position = marker.getPosition();
});
I put together a small jsfiddle with this example if you'd like to see it in action. Also, click here for full reference of the Drawing Library for the maps api.
EDIT: (start mode in marker add on map load, hide drawing controls after marker added, maker marker draggable)
To start the drawing mode to add marker on map load, simply set the drawingMode option in your drawingManager variable declaration:
`drawingMode : google.maps.drawing.OverlayType.MARKER`
You can hide the drawing controls in the markercomplete event listener:
// To hide:
drawingManager.setOptions({
drawingControl: false //changes UI back to regular map interactions
});
drawingManager.setDrawingMode(null); //hides controls
Alternatively, if you're never going to need the drawing controls again later in your client interactions you can remove it from the map complete via:
drawingManager.setMap(null);
Then to make the marker draggable, just set the option in the listener as well (because the marker in the callback function is a google maps marker object anyway - which references the marker that's added to your map).
marker.setOptions({
draggable: true
});
You can then add a listener on the marker object for the dragend event to track changes to the location.
Here's in updated fiddle: http://jsfiddle.net/svigna/J5zMg/3/

Google Maps API v3: Markers not being removed

I'm creating a map that loads & destroys markers based on both the bounding box and zoom level. I'm having a real problem getting markers to properly be removed, it seems to work sometimes for certain situations.
I have an object that contains the marker info, which also contains the google maps marker object. My code detects if the market should be deleted based on the bounding box or zoom-level. I set the marker object to "setMap(null);" and using firebug I can see that its being set, I then remove the parent object entirely and the objects data length is updated properly.
I output to the firebug console when a marker is supposedly deleted, seems to be working and I can see that the marker isn't being re-crated from the ajax call for markers on the boundingbox change.
Yet if I zoom around the map I can sometimes see that the markers are being removed, if I zoom away then pan back holding the mouse down. Or sometimes the markers will all be removed if I zoomout the first time, but if I zoom in again then back out they are not removed.
I must be doing something wrong with the logic of my code, I'm stumped.
You can view the source of
http://www.trailforks.com/map/test.php?lat=49.352247&lon=-123.202413
the JS is
http://www.trailforks.com/map/includes/map.js
the code for deleting a marker is at the bottom
function clearMarkerMemory(mapItem, i) {
google.maps.event.removeListener(mapItem.lis); // remove stored listener
mapper.data[i].obj.setMap(null); // remove marker
mapper.data.splice(i, 1);
console.log("removed marker "+mapItem.icon+":"+mapItem.nid+' '+mapItem.name);
};
I added some more debug into to the console, going to a simple area of the map with only 2 markers http://www.trailforks.com/map/test.php?lat=49.43210641783767&lon=-123.49878636730955&z=14
I can see the markers created, then move the map a bit and see that the markers weren't re-created because they were detected in the marker object. I then move the viewport so one of the markers is off the screen and I can see that the marker is removed and the marker object length updates. But if I pan the map back over the marker is still on the map.
I was struggling with similar problem for a long while until I realized that the map marker's setMap-method is asynchronous. When you call that and immediately remove any references to that marker object, the browser's garbage collector steps in and cleans it up from the memory and thus prevents the actual remove operation from happening.
Try it out by just commenting out the line with the splice call and see if that helps. If it does help, you should consider delaying the removal of the object, or alternatively storing the reference to the marker object until it's really removed. How to detect if it's really removed? I have no idea.
I hope this helps!
Instead of doing:
google.maps.event.addListener(map, 'dragend', function() { refreshMarkers(); }); //refresh markers when user moves map
google.maps.event.addListener(map, 'zoom_changed', function() { refreshMarkers(); }); //refresh markers when user moves map
change it to:
EDIT, (after comments):
To prevent multiple instances of the event handler occurring simultaneously, a global variable could be used, as follows:
google.maps.event.addListener(map, 'bounds_changed', function() {
if (processing) { // var processing is global
return;
}
processing = true;
refreshMarkers();
processing = false;
}); //refresh markers when user moves map
That should cover both situations. As it is now, with two different event listeners, the AJAX calls could be conflicting, and you maybe firing a second call before the first one has completed.

Obtaining latLng of cursor/mouse when triggered by a PolyMouseEvent

I am new to the Google Maps API... so I apologize in advance if the answer to this question is somewhat basic... I have spent several hours trying to find a solution.
Explanation:
I would like to show an infowindow at the point the cursor was at when a click was detected while in a polygon.
I am able to open the infowindow - but am unable to determine the location to use.
It appears that the PolyMouseEvent object does not allow for getting the latLng like the MouseEvent does.
Is there a way to the the current mouse position (in latLng) in this case?
Set clickable:false in the PolygonOptions and listen for the click event on the map itself.

Google maps: Can't click marker which is on top of another

I have a map with about hundred location points (markers). Which are grouped with ClusterMarker http://googlemapsapi.martinpearman.co.uk/clustermarker
And then there's one "main" marker, which is draggable.
If main marker location is overlapping with other marker then it becomes undraggable. Or in another words: clicking takes action on marker which is behind the main marker.
Weird, because I'm setting zIndexProcess when creating the main marker, which brings it to the front of others (by default it's not like that).
So.. I don't know what's the problem and how to ask but I would try like this: How to get clickable area to the front if I have brought to the front main marker icon already? (at least it is visible on top of others)
P.S. I have GPolygon drawn on the base of main marker (radius, a circle) and this circle is drawn behind all markers. Don't know if this is relevant. Oh, and I can't bring this polygon to the front (seems like zIndexProcess does not work on this)
I had a similar situation and what you can do is pass the event through to another object. In my example here if the condition is met then I pass the event (by triggering it) on the map itself. You could do a similar check to see if the event point is inside a visible polygon (I won't put that code here as it should be relatively easily doable) and pass the click event onto the polygon.
Here is the code (lightly modified) that I use:
google.maps.event.addListener(this.intLineObj ,"click", function(latlng) {
if (<condition>)
{
//pass the event down to the map
google.maps.event.trigger(map, "click", latlng);
} else {
//do stuff
}
});
I hope that helps.