I need to allow users to create polylines on a google map and also allow them to delete a node between the polylines they created. The result of this removal should be a new polyline connecting the two new neighboring nodes. At the moment I'm struggling with allowing a user to delete a node. I've researched a bit and found a google reference and this SO question. Unfortunately, both of them assume that I have a reference to the polyline somewhere, which I don't, since the polyline is being created dynamically by the user.
This is the code that I currently use :
function initialize() {
var mapOptions = {
center: { lat: 45.797436, lng: 24.152044 },
zoom: 12
};
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
var drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.MARKER,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [
google.maps.drawing.OverlayType.MARKER,
google.maps.drawing.OverlayType.POLYLINE
]
},
markerOptions: {
icon: '/Mvc/Content/Styles/dropDownArrow.png'
},
polylineOptions: {
editable: true,
}
});
drawingManager.setMap(map);
google.maps.event.addListener(drawingManager, 'markercomplete', markerCompleted);
google.maps.event.addListener(drawingManager, 'polylinecomplete', polylineCompleted);
function markerCompleted(marker) {
var coordinates = { lng: marker.getPosition().lng(), lat: marker.getPosition().lat() };
alert('The coordinates for the new marker are: lat:' + coordinates.lat + ', long: ' + coordinates.lng);
}
function polylineCompleted(polyline) {
}
}
google.maps.event.addDomListener(window, 'load', initialize);
What I've tried is to map the polyline parameter inside the polylineCompleted event handler to a global variable, and then use the solution found in the SO link to somehow update the polyline, after which, using the getMap() and setMap() functions of the DrawingManager class, to update the map, but I got stuck. Is there any way of allowing a user to delete a polyline node, without having a reference to the polyline object?
Not sure this is what you are trying to achieve, but here is an example on how to let a user add and remove nodes from a polyline without using the drawingManager.
var map, polyline, markers = new Array();
function initialize() {
var mapOptions = {
zoom: 6,
center: new google.maps.LatLng(20.291, 153.027),
mapTypeId: google.maps.MapTypeId.TERRAIN
};
map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
polyline = new google.maps.Polyline({
strokeColor: 'red',
strokeWeight: 1,
map: map
});
google.maps.event.addListener(map, 'click', function (event) {
addPoint(event.latLng);
});
}
function removePoint(marker) {
for (var i = 0; i < markers.length; i++) {
if (markers[i] === marker) {
markers[i].setMap(null);
markers.splice(i, 1);
polyline.getPath().removeAt(i);
}
}
}
function addPoint(latlng) {
var marker = new google.maps.Marker({
position: latlng,
map: map
});
markers.push(marker);
polyline.getPath().setAt(markers.length - 1, latlng);
google.maps.event.addListener(marker, 'click', function (event) {
removePoint(marker);
});
}
initialize();
JSFiddle demo
Click on the map to add a point and click on a marker to remove a point.
Related
I am using this sample code to add a cluster of markers and infoWindows (and related event listeners) to my map:
function initMap(locations) {
var myLatLng = {lat: 41.69906, lng: 12.39258};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 5,
center: myLatLng,
mapTypeControl: false,
scaleControl: false
});
var infoWin = new google.maps.InfoWindow();
var markers = locations.map(function(location, i) {
var marker = new google.maps.Marker({
position: location
});
google.maps.event.addListener(marker, 'click', function(evt) {
content = <..some HTML content...>;
infoWin.setContent(content);
infoWin.open(map, marker);
})
return marker;
});
The "locations" variable contains around 1,000 markers with lat/long and name.
The question is: are 1,000 markers too much in terms of performance/memory load? How can I free memory when the application leaves the map to show other data?
I have created an application that allows a user to plot a flag on google maps upon a click event although once the page is refreshed all of flags are lost. I want to be able to keep the data the user has input using local storage, can anyone point me in a direction or show me sample code of how they would handle this problem? thanks.
Basic google maps code without local storage
var map;
var myCenter=new google.maps.LatLng(54.906435, -1.383944);
function initialize()
{
var mapProp = {
center:myCenter,
zoom:13,
mapTypeId:google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("googleMap"),mapProp);
//creating the event for placing the marker
google.maps.event.addListener(map, 'click', function(event) {
placeMarker(event.latLng);
});
}
//Funcion to place the marker on the map (flag)
function placeMarker(location) {
var marker = new google.maps.Marker({
position: location,
icon:'flag.png',
map: map,
});
//open information window once marker is placed
var infowindow = new google.maps.InfoWindow({
content: 'User has placed warning'
});
infowindow.open(map,marker);
//zoom into the marker
google.maps.event.addListener(marker,'click',function() {
map.setZoom(17);
map.setCenter(marker.getPosition());
});
}
google.maps.event.addDomListener(window, 'load', initialize);
This should do the trick ;)
function initialize()
{
var mapProp = {
center:myCenter,
zoom:13,
mapTypeId:google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("googleMap"),mapProp);
//creating the event for placing the marker
google.maps.event.addListener(map, 'click', function(event) {
writeToStorage(event.latLng);
placeMarker(event.latLng);
});
setupStorage();
readFromStorage();
}
function setupStorage() {
if(typeof(localStorage) === "undefined") {
// If localStorage isn't supported, fake it.
// Won't persist between sessions.
localStorage = {};
}
localStorage.locations = localStorage.locations || [];
}
function writeToStorage(location) {
localStorage.locations.push(location);
}
function readFromStorage() {
localStorage.locations.forEach(function(location) {
placeMarker(location);
});
}
//Funcion to place the marker on the map (flag)
function placeMarker(location) {
var marker = new google.maps.Marker({
position: location,
icon:'flag.png',
map: map,
});
//open information window once marker is placed
var infowindow = new google.maps.InfoWindow({
content: 'User has placed warning'
});
infowindow.open(map,marker);
//zoom into the marker
google.maps.event.addListener(marker,'click',function() {
map.setZoom(17);
map.setCenter(marker.getPosition());
});
}
google.maps.event.addDomListener(window, 'load', initialize);
Let me know if you have any trouble understanding any of it.
var map = {};
var polyOptions = {};
$(document).ready(function () {
map = new google.maps.Map(document.getElementById('MapDiagram'), {
zoom: 5.4,
center: new google.maps.LatLng(40, -10),
mapTypeId: google.maps.MapTypeId.ROADMAP,
zoomControl: true
});
polyOptions = {
strokeWeight: 0,
fillOpacity: 0.45,
editable: true
};
});
map.setCenter(new google.maps.LatLng(coord1, coord2));
My main goal with the program in question is to generate a Google map that shows the location of a specific building.
Due to Google limitation reasons, I have generated and stored all latitudes and longitudes for all the buildings that I analyze in a MS SQL database(it is a real estate web site). Everytime one building is selected then I retreive its corresponding latitud and longitude and store it in two asp:Label's. I use a script in Javascript in order to process the latitud and longitud which are passed on via two asp:Label's. My problem is that for some reason the LatLng function does not seem to work property and my maps do not show the coordinates that they should. I think I may have a problem with the type of variable that LatLng is expecting. I have tried both, default string that is passed on and converting the variables to real type. Here is the script. Any help or suggestions are appreciated:
<script type="text/javascript">
(function () {
// Defining global variables
var map, geocoder, marker, infowindow, propertyaddress, selectedbuilding, maplatitude, maplongitude, buildinglatlng, latlng, myOptions;
function InitializeMap() {
//propertyaddress = '400 Alton Road, Miami Beach, FL 33139';
propertyaddress = document.getElementById('<%=lblselectedHiddenBuildingAddress.ClientID%>').innerText;
selectedbuilding = document.getElementById('<%=lblMainBuilding.ClientID%>').innerText;
//maplatitude = parseFloat(document.getElementById('<%=lblCoordinateLatitud.ClientID%>').innerText);
//maplongitude = parseFloat(document.getElementById('<%=lblCoordinateLongitud.ClientID%>').innerText);
maplatitude = document.getElementById('<%=lblCoordinateLatitud.ClientID%>').innerText;
maplongitude = document.getElementById('<%=lblCoordinateLongitud.ClientID%>').innerText;
buildinglatlng = new google.maps.LatLng(maplatitude, maplongitude);
//window.alert("Processed propertyaddress");
//latlng = new google.maps.LatLng(25.76804, -80.132743);
// Creating an object literal containing the properties
// we want to pass to the map
myOptions = {
zoom: 15,
center: new google.maps.LatLng(maplatitude, maplongitude),
//center: buildinglatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
scaleControl: true,
streetViewControl: true,
disableDefaultUI: true,
mapTypeControl: true,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
position: google.maps.ControlPosition.TOP_LEFT,
mapTypeIds: [
google.maps.MapTypeId.ROADMAP,
google.maps.MapTypeId.TERRAIN,
google.maps.MapTypeId.SATELLITE
]
},
navigationControl: true,
navigationControlOptions: {
position: google.maps.ControlPosition.TOP_LEFT
}
};
// Creating the map
map = new google.maps.Map(document.getElementById("map"), myOptions);
}
window.onload = InitializeMap;
})();
</script>
#
Added Code that Works but uses the geocoder
#
For instance the following code works perfectly but it uses the geocoder. Passing the variables is not a problem. There is something strange with LatLng and what it does with the variables passed. It does get the values with all the significant places though.
<script type="text/javascript">
(function () {
// Defining global variables
var map, geocoder, marker, infowindow, propertyaddress, selectedbuilding, maplatitude, maplongitude, buildinglatlng, latlng, myOptions;
function InitializeMap() {
//propertyaddress = '400 Alton Road, Miami Beach, FL 33139';
propertyaddress = document.getElementById('<%=lblselectedHiddenBuildingAddress.ClientID%>').innerText;
selectedbuilding = document.getElementById('<%=lblMainBuilding.ClientID%>').innerText;
//maplatitude = parseFloat(document.getElementById('<%=lblCoordinateLatitud.ClientID%>').innerText);
//maplongitude = parseFloat(document.getElementById('<%=lblCoordinateLongitud.ClientID%>').innerText);
maplatitude = document.getElementById('<%=lblCoordinateLatitud.ClientID%>').innerText;
maplongitude = document.getElementById('<%=lblCoordinateLongitud.ClientID%>').innerText;
buildinglatlng = new google.maps.LatLng(maplatitude, maplongitude);
//window.alert("Processed propertyaddress");
//latlng = new google.maps.LatLng(25.76804, -80.132743);
if (!geocoder) {
geocoder = new google.maps.Geocoder();
}
// Creating a GeocoderRequest object
var geocoderRequest = {
address: propertyaddress
}
geocoder.geocode(geocoderRequest, function (results, status) {
// Check if status is OK before proceeding
if (status == google.maps.GeocoderStatus.OK) {
// Center the map on the returned location
//map.setCenter(results[0].geometry.location);
// Creating an object literal containing the properties
// we want to pass to the map
myOptions = {
zoom: 15,
//center: new google.maps.LatLng(maplatitude, maplongitude),
center: results[0].geometry.location,
mapTypeId: google.maps.MapTypeId.ROADMAP,
scaleControl: true,
streetViewControl: true,
disableDefaultUI: true,
mapTypeControl: true,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
position: google.maps.ControlPosition.TOP_LEFT,
mapTypeIds: [
google.maps.MapTypeId.ROADMAP,
google.maps.MapTypeId.TERRAIN,
google.maps.MapTypeId.SATELLITE
]
},
navigationControl: true,
navigationControlOptions: {
position: google.maps.ControlPosition.TOP_LEFT
}
};
// Creating the map
map = new google.maps.Map(document.getElementById("map"), myOptions);
// Check to see if we've already got a Marker object
if (!marker) {
// Creating a new marker and adding it to the map
marker = new google.maps.Marker({
map: map,
animation: google.maps.Animation.DROP
});
google.maps.event.addListener(marker, 'click', toggleBounce);
}
// Setting the position of the marker to the returned location
marker.setPosition(results[0].geometry.location);
// Check to see if we've already got an InfoWindow object
google.maps.event.addListener(marker, 'click', function () {
if (!infowindow) {
// Creating a new InfoWindow
infowindow = new google.maps.InfoWindow();
}
// Creating the content of the InfoWindow to the address
// and the returned position
var content = '<h2>' + selectedbuilding + '</h2>';
//content += 'Lat: ' + results[0].geometry.location.lat() + '<br />';
//content += 'Lng: ' + results[0].geometry.location.lng();
// Adding the content to the InfoWindow
infowindow.setContent(content);
// Opening the InfoWindow
infowindow.open(map, marker);
});
// Triggering the click event
google.maps.event.trigger(marker, 'click');
};
});
}
function toggleBounce() {
if (marker.getAnimation() != null) {
marker.setAnimation(null);
} else {
marker.setAnimation(google.maps.Animation.BOUNCE);
}
}
window.onload = InitializeMap;
})();
</script>
Regards,
Elias
Have you verified that maplatitude and maplongitude contain the values you expect (eg. with a debugger)?
Is there any correlation between the expected location and the actual location shown on the map (for example, if the building is at N21.7684, and the marker is placed at N21.0000, the decimal places may have been lost).
I just found a post from Google where they changed the LatLng function and now you have to CAST the two parameters with NUMBER(). They claim that people were passing strings to the LatLng function and that created unpredicatable results. So I have appended my new code with the changes ... It only took three days to find this fix!!!! :-( I wonder why more people are not running into this. Here is the code:
<script type="text/javascript">
(function () {
// Defining global variables
var map, geocoder, marker, infowindow, propertyaddress, selectedbuilding, maplatitude, maplongitude, buildinglatlng, latlng, myOptions;
function InitializeMap() {
//propertyaddress = '400 Alton Road, Miami Beach, FL 33139';
propertyaddress = document.getElementById('<%=lblselectedHiddenBuildingAddress.ClientID%>').innerText;
selectedbuilding = document.getElementById('<%=lblMainBuilding.ClientID%>').innerText;
//maplatitude = parseFloat(document.getElementById('<%=lblCoordinateLatitud.ClientID%>').innerText);
//maplongitude = parseFloat(document.getElementById('<%=lblCoordinateLongitud.ClientID%>').innerText);
maplatitude = document.getElementById('<%=lblCoordinateLatitud.ClientID%>').innerText;
maplongitude = document.getElementById('<%=lblCoordinateLongitud.ClientID%>').innerText;
buildinglatlng = new google.maps.LatLng(Number(maplatitude), Number(maplongitude));
//window.alert("Processed propertyaddress");
myOptions = {
zoom: 15,
center: new google.maps.LatLng(Number(maplatitude), Number(maplongitude)),
mapTypeId: google.maps.MapTypeId.ROADMAP,
scaleControl: true,
streetViewControl: true,
disableDefaultUI: true,
mapTypeControl: true,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
position: google.maps.ControlPosition.TOP_LEFT,
mapTypeIds: [
google.maps.MapTypeId.ROADMAP,
google.maps.MapTypeId.TERRAIN,
google.maps.MapTypeId.SATELLITE
]
},
navigationControl: true,
navigationControlOptions: {
position: google.maps.ControlPosition.TOP_LEFT
}
};
// Creating the map
map = new google.maps.Map(document.getElementById("map"), myOptions);
// Check to see if we've already got a Marker object
if (!marker) {
// Creating a new marker and adding it to the map
marker = new google.maps.Marker({
map: map,
animation: google.maps.Animation.DROP
});
google.maps.event.addListener(marker, 'click', toggleBounce);
}
// Setting the position of the marker to the returned location
marker.setPosition(buildinglatlng);
// Check to see if we've already got an InfoWindow object
google.maps.event.addListener(marker, 'click', function () {
if (!infowindow) {
// Creating a new InfoWindow
infowindow = new google.maps.InfoWindow();
}
// Creating the content of the InfoWindow to the address
// and the returned position
var content = '<h2>' + selectedbuilding + '</h2>';
// Adding the content to the InfoWindow
infowindow.setContent(content);
// Opening the InfoWindow
infowindow.open(map, marker);
});
// Triggering the click event
google.maps.event.trigger(marker, 'click');
}
function toggleBounce() {
if (marker.getAnimation() != null) {
marker.setAnimation(null);
} else {
marker.setAnimation(google.maps.Animation.BOUNCE);
}
}
window.onload = InitializeMap;
})();
</script>
I have three arrays : myLats, (latitudes) myLngs (longitudes) and myLocs (address strings)
e.g. myLats[0] = 53.3534751, ,myLngs[0] = -2.5682085, myLocs[0] = Longwood Rd Appleton Warrington. So the elements of each array all correspond to each other numerically.
When constructing the map in my initialize() function, I loop through these to place multiple markers at the correct coordinates, and i'm also trying to have each marker having an infowindow appear when clicked, yet when i click a marker an infowindow simply does not appear. Any help with this would be greatly appreciated.
Code:
function initialize() {
var myOptions = {
center: new google.maps.LatLng(54.00366, -2.547855),
zoom: 6,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById('map_canvas'), myOptions);
var marker, infowindow, i;
for (i = 0; i <= myLats.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(myLats[i], myLngs[i]),
map: map,
clickable: true,
icon: '". url::base() ."resources/icons/accident.png',
});
infowindow = new google.maps.InfoWindow({
content: myLocs[i],
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.open(map, marker);
});
}
}
That's a common problem when dealing with more than one marker. You aren't in fact creating a new window for each marker but must redefining the single window for each marker.
You'll find the problem and solution on page 88 onwards of Google Map API V3
If you are new to Google Maps API, I would recommend reading that book, it gave me a great start and I avoided a lot of the "common" mistakes.
Hope this helps.
Jim
I made a few changes, like adding the markers inside a function, adding 'var', and changing i <= myLats.length to i < myLats.length. It was a combination of these changes that made it work.
var myLats = [ 54.20366, 54.42366, 54.64366];
var myLngs = [ -2.54788, -2.66788, -2.78788];
var myLocs = [ "Loc a" , "Loc b" , "Loc c"];
function initialize()
{
var myOptions =
{
center: new google.maps.LatLng(54.00366,-2.547855),
zoom: 6,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById('map_canvas'),myOptions);
var marker, infowindow, i;
for (i=0; i < myLats.length; i++)
{
addMarker(i);
}
function addMarker(i) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(myLats[i],myLngs[i]),
map: map,
clickable: true,
//icon: '". url::base() ."resources/icons/accident.png',
});
var infowindow = new google.maps.InfoWindow({
content: myLocs[i]
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
}
}
However, I'm guessing you want a solution that keeps only one infowindow open, I had this figured out first:
var myLats = [ 54.20366, 54.42366, 54.64366];
var myLngs = [ -2.54788, -2.66788, -2.78788];
var myLocs = [ "Loc a" , "Loc b" , "Loc c"];
var map, marker, infowindow, i;
function initialize()
{
var myOptions =
{
center: new google.maps.LatLng(54.00366,-2.547855),
zoom: 6,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map_canvas'),myOptions);
infowindow = new google.maps.InfoWindow({ });
for (i = 0; i < myLats.length; i++) {
addMarker(i);
}
}
function addMarker(i) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(myLats[i],myLngs[i]),
map: map,
clickable: true
//icon: '". url::base() ."resources/icons/accident.png'
});
google.maps.event.addListener(marker, 'click', function(event) {
infowindow.setContent(myLocs[i]);
infowindow.open(map,marker);
});
}
I've been digging around everywhere and I can't seem to figure this out. It's driving me crazy! I'm a newbie to javascript in general, so I can't quite put a finger on the translation that would fix my issue. I noticed that a lot of people have this problem, but they all seem to use more advanced(or just confusing) code than I. Anyway, here goes!
I've been having the problem where all of my markers share the same content.
function initialize() {
var myOptions = {
center: new google.maps.LatLng(34.151271, -118.449537),
zoom: 9,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: false,
streetViewControl: false,
panControl: false,
zoomControl: true,
zoomControlOptions: { style: google.maps.ZoomControlStyle.SMALL },
};
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
setMarkers(map, clubs);
}
var clubs = [
['Poop', 34.223868, -118.601575, 'Dookie'],
['Test Poop', 34.151271, -118.449537, 'Test Business']
];
function setMarkers(map, locations) {
var image = new google.maps.MarkerImage('images/image.png',
new google.maps.Size(25, 32),
new google.maps.Point(0,0),
new google.maps.Point(0, 32)
);
var shape = {
coord: [1, 1, 1, 20, 18, 20, 18 , 1],
type: 'poly'
};
for (var i = 0; i < locations.length; i++) {
var club = locations[i];
var myLatLng = new google.maps.LatLng(club[1], club[2]);
var infowindow = new google.maps.InfoWindow();
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
icon: image,
shape: shape,
title: club[0],
});
google.maps.event.addListener(marker, 'click', function(){
infowindow.setContent(club[3]);
infowindow.open(map, this);
});
}
}
I know I'm crappy, but someone please help me! :P
The problem is because you're setting the event listener for the marker click within a loop. So all the markers end up only getting the content for the last of your markers. Try this instead. Create a new global function:
function bindInfoWindow(marker, map, infowindow, html) {
marker.addListener('click', function() {
infowindow.setContent(html);
infowindow.open(map, this);
});
}
Then within your loop, replace this:
google.maps.event.addListener(marker, 'click', function(){
infowindow.setContent(club[3]);
infowindow.open(map, this);
});
with this:
// add an event listener for this marker
bindInfoWindow(marker, map, infowindow, club[3]);
When setting the marker object (var marker = new ...) change this line: "title: club[0]," to "title: club[i],". Yes, just change the 0 to i.
That should solve the problem.
Try this link for a tutorial on Google Maps API with examples.
http://code.google.com/apis/maps/documentation/javascript/tutorial.html
It should be very easy and helpful.