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);
});
Related
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/
I have a layer of centerpoints derived from polygons via an OnEachFeature event.
The first part of the behavior I'm looking for is for the polygon associated with that centerpoint to change style when clicked upon, which I've been successful at.
var ProjectMap = L.esri.featureLayer ({
url: 'https://services.arcgis.com/2gdL2gxYNFY2TOUb/arcgis/rest/services/NECSC_Test_Data/FeatureServer/1',
//making the polygons invisible
weight: 0,
fillOpacity: 0,
onEachFeature: function(feature,layer){
if (feature.geometry.type = 'Polygon') {
var bounds = layer.getBounds();
var center = bounds.getCenter();
var centerpoints = L.marker(center);
centerpointlayer.addLayer(centerpoints);
centerpoints.on('click', function(e) {
map.fitBounds(bounds);
layer.setStyle({
fillOpacity: 0.5,
});
info.update(layer.feature.properties);
});
};
}
}).addTo(map);
The second part of the behavior I want is for any previously clicked polygon to reset its style when a different centerpoint is clicked. I can't get this to work using e.target and e.layer and the GeoJSON resetStyle method, as suggested in many other threads on here.
[...]
var selected
centerpoints.on('click', function(e) {
if (selected){
e.target.resetStyle(selected)
}
selected = e.layer
map.fitBounds(bounds);
selected.setStyle({
fillOpacity: 0.5,
});
info.update(layer.feature.properties);
});
The console throws back an error at me, at selected.setStyle({ of
'Uncaught TypeError: Cannot read property 'setStyle' of undefined' at e.<anonymous> ((index):178)
at e.fire (leaflet.js:5)
at e._fireDOMEvent (leaflet.js:5)
at e._handleDOMEvent (leaflet.js:5)
at HTMLDivElement.r (leaflet.js:5)
I'm a bit stumped at what's going on with Leaflet here-- is there another way to go about getting the esri.feature.layer to reset back to its default style, then changing the style of the selected centerpoint-polygon combo on click?
I believe you need to listen to the click event on the layer and not the markers.
centerpointlayer.on('click', function(e) {
if (selected){
e.target.resetStyle(selected)
}
selected = e.layer
map.fitBounds(bounds);
selected.setStyle({
fillOpacity: 0.5,
});
info.update(layer.feature.properties);
});
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 click event that grabs coordinates remotely, lays them on a map, and connects them with a polyline. I have other click events that do the same, but want to keep them as a separate layer so that the user can toggle to view each of the clicks they have done. Does anyone know of a good way to group them separately to do this or another approach?
Here is my code so far:
drawPoints: function (points, color) {
$.each(points, function (key, val) {
var location = new google.maps.LatLng(val.Latitude, val.Longitude);
MyTest.addMarker(location, val.Name, val.Description);
MyTest.coordinates.push(location);
});
this.path = new google.maps.Polyline({
path: MyATest.coordinates,
strokeColor: color,
strokeOpacity: 1.0,
strokeWeight: 2
});
this.path.setMap(this.googlemap);
},
addMarker: function (location, title, html) {
var marker = new google.maps.Marker({
position: location,
map: this.googlemap,
title: title,
html: html
});
this.markers.push(marker);
},
// Removes the overlays from the map, but keeps them in the array
clearOverlays: function () {
if (this.markers) {
for (i in this.markers) {
this.markers[i].setMap(null);
}
}
},
// Shows any overlays currently in the array
showOverlays: function () {
if (this.markers) {
for (i in this.markers) {
this.markers[i].setMap(map);
}
}
},
You've got them kept in this.markers - which is a great start. Now all you need to do is define a click listener function for each marker:
for(i in this.markers) {
google.maps.addListener(this.markers[i], function() {
this.markers[i].clicked = true; });
}
Then, whenever a user wants to toggle only the markers they've clicked on, loop through your markers (like you are doing) and setMap to null on all where this.markers[i].clicked === undefined.
I've a complex flow where I've to attach mouseover event for every polyline on the map. The code for attaching the event is simple:
google.maps.event.addListener(polyline, "mouseover", function() {
console.log('event fired');
});
But the event is attaching to few polylines and not to others. What might be the reason?
Edit
Following is some more code that is before the above code and used for defining polyline:
this.polyline = new google.maps.Polyline({
path : [fromPosition, toPosition],
strokeColor : '#CCCCCC',
strokeOpacity : 1.0,
strokeWeight : 2
});
var polyline = this.polyline;
Edit 05-Apr-2012
Following is the code that creates problem, Please explain why it's happening and recommend any solution. Thanks
function Link(from, to) {
this.from = from;
this.to = to;
}
Link.prototype.show = function() {
this.line = new google.maps.Polyline({
path : [this.from, this.to],
strokeColor : "#0000FF",
strokeOpacity : 0.5,
strokeWeight : 6
});
this.line.setMap(map);
google.maps.event.addListener(this.line, 'mouseover', function() {
this.line.setOptions({
strokeOpacity : 1
});
});
google.maps.event.addListener(this.line, 'mouseout', function() {
this.line.setOptions({
strokeOpacity : 0.5
});
});
}
var links = [];
var link2 = new Link(new google.maps.LatLng(-3.5999999999999996, 23.4), new google.maps.LatLng(-4.5, 23.4)), link1 = new Link(new google.maps.LatLng(-3.5999999999999996, 23.4), new google.maps.LatLng(-3.5999999999999996, 18));
links.push(link1);
links.push(link2);
// I've a long list of links, so I'll prefer a loop
for(var i = 0; i < links.length; i++) {
links[i].show();
}
JSFiddle Demo : http://jsfiddle.net/wasimbhalli/9bg6x/
demo: http://jsfiddle.net/kbngxku9/
var map;
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(-3, 23),
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('mapcanvas'), mapOptions);
var bounds = [];
var bounds_group_1 = [new google.maps.LatLng(-3.5999999999999996, 23.4), new google.maps.LatLng(-4.5, 23.4)],
bounds_group_2 = [new google.maps.LatLng(-3.5999999999999996, 23.4), new google.maps.LatLng(-3.5999999999999996, 18)];
bounds.push(bounds_group_1);
bounds.push(bounds_group_2);
for (var i = 0; i < bounds.length; i++) {
addPolylineSegment(bounds[i]);
}
}
function addPolylineSegment(bounds) {
// optionally you can put each polyline
// segment into an array to later use...
var polyline;
polyline = new google.maps.Polyline({
path: bounds,
strokeColor: "#0000FF",
strokeOpacity: 0.5,
strokeWeight: 6
});
polyline.setMap(map);
// attach event listener to each segment...
google.maps.event.addListener(polyline, 'mouseover', function(event) {
this.setOptions({
strokeOpacity: 1
});
});
google.maps.event.addListener(polyline, 'mouseout', function(event) {
this.setOptions({
strokeOpacity: 0.5
});
});
}
google.maps.event.addDomListener(window, 'load', initialize);
OK, I'm trying to keep the solution close to your code. The key was changing both listener's this.line.setOptions to this.setOptions:
google.maps.event.addListener(this.line, 'mouseover', function() {
this.setOptions({
strokeOpacity : 1
});
});
google.maps.event.addListener(this.line, 'mouseout', function() {
this.setOptions({
strokeOpacity : 0.5
});
});
I've seen a similar case with markers in another question. I believe this inside the function() already refers to the first argument of addListener(), in this case, this.line, so you are covered just saying this. Here is the jsfiddle:
http://jsfiddle.net/zfFsD/
The other change I made was putting the links[] code in my initialize(). Wish you the best!
I think you have a scope problem.
change
this.line.setOptions
with
this.setOptions
Firebug and console.log() are your friends :)
I managed to work around this using the method described below. If I understood you correctly, the loop in which you attach a listener to a polyline does not in fact get "attached" to the polyline that way, but instead, you need a new class instance that contains the polyline and the listeners. This way, each polyline gets it's own listener.
Please, see the explanation below.
EDIT 5.4.2012
Here's also a crude JSFiddle demonstration of the code in action. Link to JSFiddle demo
function initialize() {
// initialize Google Maps canvas normally
var polylines = [];
// Data set of the polylines you want to present on the map,
// e.g. [ { lat:"...",lon:"..." }, ...]
var polylineData = [{ ... }]
for ( i in polylineData ) {
var line = new google.maps.Polyline({
path: [/*coordinates as google.maps.LatLng objects*/]
});
// Create a new myPolyLineClass instance that contains the polyline data
// and push it to polylines array.
polylines.push(new myPolyLineClass(line));
}
// Set all the polylines and their individual listeners on map
for ( i in polylines) {
polylines[i].line.setMap(map);
}
}
function MyPolylineClass(lineData) {
this.line = lineData;
// + all other data you want the polylines to contain
// Add listeners using google.maps.event.addListener to all class instances
// when they are constructed.
// for instance:
google.maps.event.addListener(line, 'mouseover', function() {
line.setOptions({ [options you want to set when area is hovered
and selected] });
});
// Add listeners also for when polyline is not hovered anymore, respectively,
// and other methods you might want to call when polylines are being interacted with.
};
Hope this helps!
Cheers