Undo drawing a polygon vertex (google maps API v3) - google-maps

I'm trying to find a way to create an undo button for drawing that works similarly to the undo button that is available while editing the polygon.
To be more precise, whenever a user inserts a point on the map which is for example a vertex of a polygon, he should have an option to undo his last (point/vertext) insertion.
Currently it doesn't exist as an existing functionality and I was hoping that it would be easy to implement it in the application I'm developing, but to me it seems there's no way to approach to the objects and layers created on the map before they are complete.
It's either that in v3 API there's almost everything exposured except this, or that I'm looking at the wrong place.
Apart from 'polygoncomplete' there are no other useful drawing events for shapes and it seems that the maintaned state for drawing activities is deeply rooted and scattered as I couldn't just go and replace map object and canvas elements with their previous versions.
Any hopes?

I've created script based on google manual for vertex deleting. The main function is simple, prototype is based on google.maps.OverlayView.
function DeleteMenu() {
this.div_ = document.createElement('div');
this.div_.className = 'delete-menu';
var menu = this;
google.maps.event.addDomListener(this.div_, 'click', function(e) {
menu.removeVertex();
e.stopPropagation();
});
}
DeleteMenu.prototype = new google.maps.OverlayView();
Gist with code is here. Use jsbin sandbox to play with it.
View example page, just click on the map to build your path, you can see undo button.

Related

Get all Google Map v3 markers loaded from GeoJSON

I load data for my Google Maps v3 with GeoJSON:
that.map = new google.maps.Map($('#map')[0], mapOptions);
that.map.data.loadGeoJson('http://localhost/geoserver/...');
Now, at some point on some user event I need to get one marker and paint it blue.
I can set different color with setIcon.
My idea is to get all features, then iterate through them, find the right feature (based on UNIQUE feature data field) and find marker behind that feature and change icon. I found some approaches that store all markers in array, but don't know why I need another array. Computer resources are important and I don't want to duplicate things.
I need help with, how to get features and how to get Marker object associated with selected feature. If there is a better way to do it, please...
UPDATE
I found this:
var feature = this.map.data.getFeatureById(ID);
I just need to get feature Marker. How? Doesn't look that Feature class has method for that?
There is no method/property that gives you access to the shape(marker,polygon,etc.) that has been created by the API.
To set a new icon-property for a particular feature use overrideStyle:
map.data.overrideStyle(feature, {icon: newIconSettings});
Another option is:
that.map.data.setStyle(function(feature)
{
var color = 'red';
if (feature.getProperty('color'))
{
color = feature.getProperty('color');
}
return ({ // #type {google.maps.Data.StyleOptions}
icon: 'http://maps.google.com/mapfiles/ms/icons/' + color + '-dot.png',
});
});
But it is not as good as Dr. Molle solution, because it needs to iterate through entire features set. I found it on google api documentation (look for title Change Appearance Dynamically).

How to properly hide markers in google maps?

I am trying to add a bunch of markers to a map with show/hide buttons for each category of markers. Adding a marker from stored db data puts them on the map and makes them clickable, but they won't respond to setMap(null) unless that call is through google.event.addListener(marker, ...). Calling it from a standard js button onclick event, or via google.event.addDomListener(marker, ...) doesn't work.
Also maybe helpful to note is that when I call marker.setAnimation(BOUNCE) the marker starts bouncing but it looks like there is a duplicate marker under it. Similarly, if I drag the marker it's as if an unmovable duplicate is created right under it.
Thoughts? This is super frustrating!
Just like this taken from here ? Are you trying to avoid google maps api's google.maps.event.addDomListener? Why? You can use it to listen to your button's click event too. just as in:
var YourButton = document.getElementById('myButton');
function HideMarkers() {
// Hide us
}
google.maps.event.addDomListener(YourButton, 'click', HideMarkers);
customized for you from. For the second part, seeming like double markers I suppose we need some code..
This turned out to be purely user error. I am using firebase to store map data without a server backend and was adding duplicate markers. This explains the "inability to hide" and also the appearance of duplicate markers when dragging or animating.
The reason it was working from a click event on the marker was that both duplicate markers were receiving the click event and so both were being hidden.
setMap appears to be perfectly reliable when used in or out of google event handlers.

Google maps and raising marker

I'm writing web app that uses google maps. I've got some points placed to the map as markers. When I drag the marker - it raises - and when I drop it - it falls back down. I want to avoid raising marker. Is there any way to drag it without raising?
This feature has probably been added since the question was asked but stopping the marker from raising is quite straight forward now.
When creating Marker set its 'raiseOnDrag' property to false. Like so...
marker = new google.maps.Marker ({draggable : true, raiseOnDrag : false});
Since there is no option while creating the marker I guess there is no way.
The only thing, I could imagine would be using the icons (in the reference there is an example).
But you have to try, I don't know if selfmade icons are raised or not.
You can use marker.setAnimation() method:
var marker = new google.maps.Marker({...});
google.maps.event.trigger(marker, 'dragstart'); // trigger dragstart to keep marker in the "raised" state"
marker.setAnimation(3); // raise
// later
marker.setAnimation(4); // fall
In Google Maps API there are only two types of animations documented (BOUNCE and DROP), but I have discovered two more:
1: BOUNCE,
2: DROP,
3: raise,
4: fall

HTML5 Canvas Placemark for Google Maps API v3

I'm looking for a way to generate complex Placemarks (or overlays that are "attached" to placemarks).
Is there a way (I haven't found it) with the Map v3 api to attach/overlay a on placemark?
Or, will I need to draw outside of the Google api and then have listener/s that trigger redrawing when the user pans the map?
You extend google.maps.OverlayView with an object that override onAdd(), draw(), and onRemove()
In onAdd you'll probably want to set up a reference to a pane in google.maps.MapPanes to put your markup into. Then you'll have to handle the pan and zoom events. You do that like so:
CustomOverlayView.prototype.initPanes = function() {
var panes = this.getPanes(); //object of type google.maps.MapPanes
this.drawPane = jQuery(panes.floatPane); //we will initialize our stuff in this div element
this.drawPane.attr("id", "map-draw-pane"); //conceivable to want to reference this, usefull for debugging
this.drawPane.css("background-color", "transparent"); //DONT COVER THE GOOGLE COPYRIGHT
};
In order for your canvas to be useful for drawing, you need a way to convert your google.maps.LatLng objects into Point objects with x and y variables. The answer is in google.maps.MapCanvasProjection which has various methods that compute location objects encoded as google.maps.LatLng objects into useful pixel coordinates (and back again).
var projection = this.getProjection();//google.maps.MapCanvasProjection
var drawingLocationPoint = projection.fromLatLngToContainerPixel(markerData.location);
Some details of how to put a canvas in google maps here: http://www.samedwards.net
This is easily done, so I'm sorry an answer didn't appear sooner. Hopefully this is still useful to you.
See:
http://code.google.com/apis/maps/documentation/javascript/overlays.html#CustomOverlays
And here's an example:
http://code.google.com/apis/maps/documentation/javascript/examples/overlay-simple.html
You need to implement a Javascript class which extends OverlayView. Specifically, you will write a draw() method that the Maps API will call whenever the state of the map has been changed (e.g. it has been dragged or zoomed).
In that method you can create a HTML5 canvas (or anything really) and draw whatever you need. You get access to the underlying map projection, which lets you reliably convert LatLngs to pixels for the current zoom level and projection type.
I would recommend looking at this semi official extension library for creating a canvas overlay:
http://google-maps-utility-library-v3.googlecode.com/svn/trunk/canvaslayer/
http://google-maps-utility-library-v3.googlecode.com/svn/trunk/canvaslayer/examples/hello2d.html
as well as this sample, which uses raphael instead, but shows how you might associate your additional objects with markers:
http://gmaps-samples-v3.googlecode.com/svn/trunk/cloud/cloud.html

Google Maps v3 API: KML layer messing with click, mouse events

I'm working on a project where, after creating some nice code for creating polygons and attaching mouse events to them, the addition of KML layers (mainly placemarkers) results in uncooperative behaviour between the placeholders of the KML layer and the generated polygons.
If I create the polygons first and set the KML file afterwards, clicking on the placemarkers brings up the infowindow () as expected. However, mouseovers on the polygons below yield no result, whereas before they get highlighted and are clickable (which they aren't).
Setting the KML layer to null doesn't help either. The placemarkers disappear, but my polygons aren't registering.
When I first call the KML with placemarkers, the polygon layer called later goes on top of the placemarkers. The polygons are opaque, so you can see the placemarkers like you could through a window, but you can't click or interact with the placemarkers.
Setting the polygons to null results in the same behaviour as before. Placeholders still cannot be clicked on.
Help? I couldn't find a zIndex reference for the KML layer code, and I'm hoping that's all it is. I read somewhere else - and imagine this to be true - that the KML and user-gernated content "layers" are conflicting with one another - the latter one that's put on the map takes focus, captures events, etc. I would've thought that it wouldn't matter, in the same way that you can have divs on top of other divs, especially if you use indexing.
If you simply want to display the information in the KML layer and not have it react to user events, you can add the suppressInfoWindows flag to the constructor:
var myKmlLayer = new google.maps.KmlLayer('http://gmaps-samples.googlecode.com/svn/trunk/ggeoxml/cta.kml', { suppressInfoWindows: true });
This will effectively shut off all interactions and let your other layers receive interactions.
Edit: Forgot to mention that a good source of information is the Google API V3 site discussing KML layers