I have 2 options in my google map. -->one is polygon and another one is draw lines.Now am trying to perform undo functionality in my page.When I click undo button recently added line should be removed(that may be in either polygon option or draw line option).Is it possible?
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -34.397, lng: 150.644},
zoom: 8
});
var drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.MARKER,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: ['polygon', 'polyline']
},
circleOptions: {
strokeColor: '#00DB00',
fillColor: 'green',
fillOpacity: 0.05,
strokeWeight: 5,
clickable: false,
editable: true,
zIndex: 1
}
});
drawingManager.setMap(map);
google.maps.event.addListener(drawingManager, 'overlaycomplete', function (event)
{
if (event.type === 'marker') console.log('Lat: ' + event.overlay.position.lat() + ', Long: ' + event.overlay.position.lng())
else displayPolyLatLng(event.overlay.getPath().b);
});
function displayPolyLatLng(pointArray)
{debugger
var result=" ";
for (var i = 0; i < pointArray.length; i++)
{
result +='<b>Lat: ' + pointArray[i].lat() + ', Long: ' + pointArray[i].lng()+ '</b><br/>';
}
$('#info').html(result);
/*var lastEl = pointArray[pointArray.length-1];
alert(lastEl)
if(lastEl.length>1){
undo_redo.push(lastEl.pop());
} */
}
}
function removeLine(){
polylines.remove(polylines.size() - 1)
}
fiddle: https://jsfiddle.net/rc5p32nt/
Basically what #geocodezip said...
Keep a reference to the shapes added:
var overlays = [];
You can then push the latest overlay object event.overlay in the overlaycomplete event:
google.maps.event.addListener(drawingManager, 'overlaycomplete', function(event) {
overlays.push(event.overlay); // store reference to added overlay
});
Finally, on click of the Undo button hide the overlay via setMap(null):
// undo last overlay action
function removeLine() {
var lastOverlay = overlays.pop();
if (lastOverlay) lastOverlay.setMap(null);
}
Note that this doesn't remove the object, just hides it from showing on the map. If you want to remove the overlay completely you should then also set it to null.
You can show them again - if you wanted to add a Redo button (in this case you wouldn't pop them as I have done). See https://developers.google.com/maps/documentation/javascript/examples/polyline-remove for an example of how to implement this.
Updated demo: https://jsfiddle.net/3fe6nfdr/
My above answer explains how to remove the most recent overlay entirely.
However to remove the most recently drawn line segment of a polyline you can store a reference to the shape object in the overlaycomplete event object:
google.maps.event.addListener(drawingManager, 'overlaycomplete', function(event) {
overlays.push(event); // store reference to added overlay
});
Then using that determine if the object added was a polyline, grab the path array with overlay.getpath(), and finally call its pop() function to remove the last line segment:
// undo the last line segment of a polyline
function removeLineSegment() {
var lastOverlay = overlays.length > 0 ? overlays[overlays.length - 1] : null;
if (lastOverlay && lastOverlay.type === "polyline") {
var path = lastOverlay.overlay.getPath();
path.pop(); // remove last line segment
}
}
Demo: https://jsfiddle.net/q9xxt4kt/
Related
How do I programatically in javascript define which feature is on top of another when they overlap
In This picture I clicked on the smaller geographic feature, however the information for the outer geographic feature came up. I would like to programmatically put the smaller features on top.
Here is the my code to populate the map in javascript-
map.data.loadGeoJson('<path to my geojson definition>');
map.data.setStyle(function (feature) {
let color = 'gray';
console.log(feature);
if (feature.getProperty('isColorful')) {
color = 'blue';
}
return ({
fillColor: color,
strokeColor: color,
strokeWeight: 1
});
});
map.data.addListener('click', function (event) {
let name = event.feature.getProperty('name');
let contentString = '<h4>Polygon Info</h4><br>';
contentString += '<p>';
if (name) {
contentString += '<b>Name:</b>' + name + '<br>';
}
contentString += '</p>';
let infowindow = new google.maps.InfoWindow({
content: contentString,
position: event.latLng
});
infowindow.open(map);
event.feature.setProperty('isColorful', true);
});
Note I reversed the order of the features in the geojson file itself and that did not change the behavior.
You can use the z-index property of feature.Assuming you can disinguish one feature entry from another you can adjust z-index depending on your need in setStyle() function, just work out appropriate values
return ({
fillColor: color,
strokeColor: color,
strokeWeight: 1,
zIndex: zIndex
});
Or update z-index when mouse enters
map.data.addListener('mouseover', function(e) {
map.data.overrideStyle(e.feature, {
//strokeColor: '#1e3a2a',
//strokeWeight: 2, /* can also change these like hover effect */
zIndex: 6
});
});
map.data.addListener('mouseout', function(e) {
map.data.revertStyle();
});
I have a problem with removing a markers on google maps. These markers are created everytime the user creates a waypoint. They have the same position as the waypoint. These markers also have an InfoBox with a button to remove the correct waypoint and marker.
Everytime a waypoint is created I push a marker to one array and an infobox to the other.
This works if I have only one waypoint. The marker and waypoint are removed. But once I have 2 or more it does not work anymore. Once I try to remove one of the waypoints the marker stays on the map, even though I call .setMap(null) and/or .setPosition(null). Everytime I remove a marker I also remove it, the waypoint and info box from their corresponding arrays. Strangely enough, when I call a function to redraw the path, the waypoint does not exist anymore (as planned), but the marker stays.
Here is the code:
var markers = {
waypoints:{
p:[],
i:[],
m:[]
}
};
var saveWaypoints = function(){
removeWaypoints();
var points = directionsRenderer.getDirections().routes[0].legs[0].via_waypoints;
for(var i=0;i<points.length;i++){
var marker = new google.maps.Marker({
map:map,
position:points[i],
icon: 'http://maps.google.com/mapfiles/ms/icons/yellow-dot.png',
id: i
});
var infobox = new InfoBox({
id: i,
position: points[i],
disableAutoPan: true,
boxStyle: {
background: "white",
opacity: 1,
width: "289px",
border: 0,
padding: 0
},
zIndex: 1E4,
isHidden: false,
pane: "floatPane",
enableEventPropagation: false,
content: 'Pozicija: ' + points[i]
});
infobox.open(map,marker);
infobox.hide();
google.maps.event.addListener(infobox,'closeclick',function(){
markers.waypoints.m[this.id_].setMap(null);
markers.waypoints.m[this.id_].setPosition(null);
markers.waypoints.m.splice(this.id_,1);
markers.waypoints.p.splice(this.id_,1);
markers.waypoints.i.splice(this.id_,1);
drawPath();
});
google.maps.event.addListener(marker,'mouseover',function(){
markers.waypoints.i[this.id].show();
});
google.maps.event.addListener(marker,'mouseout',function(){
if(markers.waypoints.i[this.id] !== undefined){
if(!markers.waypoints.i[this.id].keepOpen()){
markers.waypoints.i[this.id].hide();
}
}
});
google.maps.event.addListener(marker,'click',function(){
if(waypointDialog !== null){
waypointDialog.doNotClose(false);
waypointDialog.hide();
}
console.log(this.id);
waypointDialog = markers.waypoints.i[this.id];
waypointDialog.doNotClose(true);
});
markers.waypoints.m.push(marker);
markers.waypoints.i.push(infobox);
markers.waypoints.p.push({
location: points[i],
stopover: false
});
};
};
var removeWaypoints = function(){
if(markers.waypoints !== (null||undefined)){
markers.waypoints.p = [];
markers.waypoints.m = [];
markers.waypoints.i = [];
}
};
I think its because every time its loop, it is creating a marker which is the reason why you cannot access the previous marker, in your code, i think only the last created marker is accessible, to access all marker you should put it inside array after declaration. Try this code
var markers=[]; //initialize it on global
//and on creating marker, inside for loop add this code.
markers.push(marker);
//and to clear the markers in map try the code below
for(var i=0; i< markers.length; i++)
{
markers[i].setMap(null);
}
Alright, this has been a problem for me for 3 days, javascript closures are just not my strong suit.
I have a google map which I've applied an overlay with a series of clickable polygons. I want a specific function to run depending on the polygon clicked, which I have working. The problem is I can't figure out how to work the listener so that a function that displays an infowindow with that polygon's zip code in it. Here's the code:
for (x = 0; x < 50 && coordsObject.length > x; x++) { //Only draw 50 polygons at a time
...
//create zipcoords array
clickablePolygons.push(new google.maps.Polygon({
paths: zipCoords
, strokeColor: "#000"
, strokeOpacity: 1
, strokeWeight: 1
, fillColor: convertRatingToHex(rating)
, fillOpacity: 0.45
}));
infoWindow.push(
new google.maps.InfoWindow({
content: '<div id="gcontent">' + zip.toString() + '</div>'
})
);
//problem child
var theFunction = function(arguments, infowindow, map) {
var marker = new google.maps.Marker({
position: arguments[0].latLng
});
infowindow.open(map, marker);
};
google.maps.event.addListener(clickablePolygons[clickablePolygons.length - 1], 'click', function() {
theFunction(arguments, infoWindow[x], map); //:(
});
clickablePolygons[clickablePolygons.length - 1].setMap(map);
}
What am I doing wrong with the closure?
in your addListener call you have function() and not function(arguments). I would also create a variable pointing to the infoWindow outside the call to addlistener. The assumption is that the click event will pass in the arguments that you are expecting. It may need to be function(e,arguments).
var win = infoWindow[x];
google.maps.event.addListener(clickablePolygons[clickablePolygons.length - 1], 'click', function(arguments) {
theFunction(arguments, win, map);
});
Looks like variable scoping problem, give it a try
(function(x){
google.maps.event.addListener(clickablePolygons[clickablePolygons.length - 1], 'click', function(arg) {
theFunction(arg, infoWindow[x], map);
});
})(x);
You do not need multiple instances of an InfoWindow. Just use the methods to set the content and position when needed.
I do not understand why you are adding a marker, is that a requirement? If you just want an InfoWindow to show when the polygon is clicked you can use the MouseEvent object passed from the click event to get the current position of the click.
Here is an example: http://jsfiddle.net/bryan_weaver/akLBM/
code in the link:
var map;
var infoWindow;
var clickablePolygons = [];
function createPolygon(path, stateName) {
var poly = new google.maps.Polygon({
paths: path,
strokeColor: "#000",
strokeOpacity: 1,
strokeWeight: 1,
fillColor: "#330000",
fillOpacity: 0.45
});
//add the polygon to the array, to use later if needed.
clickablePolygons.push(poly);
//attach a click event, the first argument of the listener is the event
//you can get the position of the mouse cursor where the map
//was clicked through this.
google.maps.event.addListener(poly, "click", function (event) {
//call the setContent method and set the content for the info window
infoWindow.setContent("This state is: " + stateName);
//set the anchor of the info window, in this case
//I am using the mouse position at
//the time of the click
infoWindow.setPosition(event.latLng);
//open the info window, passing the map in which to attach it to.
infoWindow.open(map);
});
//add the polygon to the map
poly.setMap(map);
}
function initialize() {
var myLatLng =
new google.maps.LatLng(39.983994270935625, -111.02783203125);
var mapOptions = {
zoom: 5,
center: myLatLng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
//polygon coords for Utah
var utah = [
new google.maps.LatLng(41.983994270935625, -111.02783203125),
new google.maps.LatLng(42.00032514831621, -114.01611328125),
new google.maps.LatLng(36.96744946416931, -114.01611328125),
new google.maps.LatLng(37.00255267215955, -109.0283203125),
new google.maps.LatLng(40.97989806962013, -109.0283203125),
new google.maps.LatLng(41.0130657870063, -111.02783203125)];
//polygon coords for Colorado
var colorado = [
new google.maps.LatLng(40.96330795307351, -109.05029296875),
new google.maps.LatLng(36.96744946416931, -109.0283203125),
new google.maps.LatLng(37.02009820136811, -101.9970703125),
new google.maps.LatLng(40.97989806962013, -102.06298828125)];
map = new google.maps.Map($('#map')[0], mapOptions);
//create a single info window for use in the application
infoWindow = new google.maps.InfoWindow();
//add the polygon and infowindow content to the map.
createPolygon(utah, "Utah");
createPolygon(colorado, "Colorado");
}
google.maps.event.addDomListener(window, 'load', initialize);
I have a Google map with multiple POLYGON areas. I have figured out how to ZOOM IN with a single click on the polygon, and ZOOM OUT with a 'dblclick' listener and remove the listeners for them...
Once you have clicked to Zoom In, then double clicked to Zoom Out, it's not allowing me to repeat the function again. Is there a way to zoom in and out multiple times?
Here is the code I have:
//POLYGON ZONE 1 ================================
var zone1;
var triangleCoords = [
new google.maps.LatLng(29.738692, -95.399331),
new google.maps.LatLng(29.738688, -95.394781),
new google.maps.LatLng(29.737048, -95.394781),
new google.maps.LatLng(29.737048, -95.399331)
];
// Construct the polygon
// Note that we don't specify an array or arrays, but instead just
// a simple array of LatLngs in the paths property
zone1 = new google.maps.Polygon({
paths: triangleCoords,
strokeColor: "#00AEEF",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#00AEEF",
fillOpacity: 0.05,
});
zone1.setMap(map);
zone1._myBounds = new google.maps.LatLngBounds();
for (var i=0; i<triangleCoords.length; i++)
{
zone1._myBounds.extend(triangleCoords[i]);
}
var listener = google.maps.event.addListener(zone1, 'click', function () {
map.fitBounds(zone1._myBounds);
google.maps.event.removeListener(listener);
});
var listener2 = google.maps.event.addListener(zone1, 'dblclick', function() {
if (map.getZoom() > 16) map.setZoom(13);
//map.setZoom(map.getZoom() -1);
//map.setCenter(map.getCenter());
google.maps.event.removeListener(listener2);
google.maps.event.addListener(zone1, 'click', function (){
map.fitBounds(zone1._myBounds);});
});
For my other POLYGON areas, would I also have to change the variable names for them to work?
Also, the return to center doesn't seem to be working properly. If I need to ask that in a separate question I will.
The immediate problem is that you don't do the same thing in the click listener you add on dblclick:
google.maps.event.addListener(zone1, 'click', function (){
map.fitBounds(zone1._myBounds);});
vs the original:
var listener = google.maps.event.addListener(zone1, 'click', function () {
map.fitBounds(zone1._myBounds);
google.maps.event.removeListener(listener);
});
I was able to make a circle object as an overlay on my google map v3. I set its editable property to true. The next thing I wanted to do was get the coordinates of the center if the user moves the circle. For this I would need some kind of method that's triggered in response to the event. I thought I had this all set up in the initialize function as seen below. However, I'm not getting any alert boxes. So I'm assuming this functions in response to the events are not getting triggered.
function initialize() {
cityCenterLatLng = new google.maps.LatLng(cLat, cLong);
options = {
center : cityCenterLatLng,
zoom : 15,
mapTypeId : google.maps.MapTypeId.ROADMAP,
disableDefaultUI : false,
mapTypeControl : true,
streetViewControl : true,
mapTypeControlOptions : {
style : google.maps.MapTypeControlStyle.DEFAULT,
position : google.maps.ControlPosition.TOP_LEFT
}
};
map = new google.maps.Map(document.getElementById("map_canvas"), options);
$("#map_canvas").css("border", "3px solid black");
infoWindow = new google.maps.InfoWindow({});
var c = {
strokeColor: "#ff0000",
strokeOpacity: 0.8,
strokeWeight: 3,
fillColor: "#b0c4de",
fillOpacity: 0.50,
map: map,
center: cityCenterLatLng,
radius: 1000,
editable:true
};
circle = new google.maps.Circle(c);
google.maps.event.addListener(circle, 'distance_changed', function()
{
alert('Circle moved');
//displayInfo(circle);
});
google.maps.event.addListener(circle, 'position_changed', function()
{
alert('distance changed');
//displayInfo(circle);
});
}
function displayInfo(widget)
{
var info = document.getElementById('info');
info.innerHTML = 'Circle Center:' + circle.get('position') + ',Circle distance: ' +
circle.get('distance');
}
Change distance_changed to center_changed for dragged movement, and use radius_changed to detect resizing. Other events are in the docs.
https://developers.google.com/maps/documentation/javascript/reference#Circle
scroll down to 'Events'.
For the new values, inside the listener functions, write alert(circle.getCenter()); or circle.getRadius()