Little background. I have a navigation setup for when you click on a certain navigation item, it creates markers on the map. If you click on a different navigation item, it removes the previous markers and sets up new ones.
Well now I am working with polylines and trying to create the same concept here with the polylines, however I am having a difficult time. Here is what I have:
// Global variable for array of lines
var points= [];
Setup my points.
line1 = new google.maps.LatLng(line1Start, line1Finish);
line2 = new google.maps.LatLng(line2Start, line2Finish);
line3 = new google.maps.LatLng(line3Start,line3Finish);
points.push(line1, line2, line3);
Setup my polylines.
var polyline = new google.maps.Polyline({
path:points,
strokeColor:"#FF0000",
strokeOpacity:1.0,
strokeWeight:2
});
Initialize the map with lines.
polyline.setMap(map);
All works well. The lines are created and show up between my markers. Now lets remove them (or not...)
function removeLines() {
if (points) {
points.length = 0;
}
points = [];
}
removeLines() is being called at the beginning of the function to clear them, then new ones are setup. This indeed clears my points in the points array, however on the map itself the polylines still show up and do not disappear like my markers do.
What gives?!
You have to do polyline.setMap(null), that will remove the line from the map. Documentation.
polyline is just an array of LatLng objects, not individual Polylines. I think you probably need a separate array for the polylines, which you can then loop over to remove them all. Create a global array line.
var line = [];
polyline = new google.maps.Polyline({
path: points,
strokeColor: "#FF0000",
strokeOpacity: 1.0,
strokeWeight: 2
});
line.push(polyline);
Now you are pushing all the polyline objects into an array line. You can make it invisible or remove it from the map by looping it like this:
for (i=0; i<line.length; i++)
{
line[i].setMap(null); //or line[i].setVisible(false);
}
Related
I need to get the nearest marker when I move the mouse over the polyline.
The markers are on the same polyline.
The markers are hidden, and I want to display the nearest to the mouse one, then the next one and to hide the prev one.
Thanks
// SET PATH
var Path = new google.maps.Polyline({
geodesic: true,
strokeColor: '#993300',
strokeOpacity: 1.0,
strokeWeight: 4 ,
id: 123
});
Path.setMap(map);
var path = Path.getPath();
data.map(function(val){
path.push(new google.maps.LatLng(+val.lat, +val.lon));
Path.setPath(path);
})
google.maps.event.addListener(Path, 'mousemove',function(e){
console.log(e.latLng)
})
Firstly you need to make sure you need to load the geometry library when you load your google maps JavaScript API.
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=geometry">
</script>
Then, when you mouse over your polyline, loop over your markers and get the distance to all of them from the mouseover point (because you don't know which one is the closest until you check them all).
Here's one way to do it:
//your markers in an array
var markers = [];
google.maps.event.addListener(polyline,'mouseover',function(e) {
var closestMarker;
markers.reduce(function(carry,marker) {
var d = google.maps.geometry.spherical.computeDistanceBetween(marker.getPosition(),e.latLng);
if(d < carry || carry == -1) {
closestMarker = marker;
return d;
}
return carry;
},-1);
//your marker is now in the variable closestMarker
});
You can figure out how to hide and display markers very easily using the Google Maps JavaScript API marker methods
I´m placing some markers on a Google Maps holding them in a global array. With a button click the markers should disappear from the map deleting them also from the array.
// clear markers
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(null);
}
// delete marker from markers array
markers.length = 0;
markers = [];
This works like a charm and the markers disappear from the map. In the next step i´m getting some new data via ajax-call, create markers again and add these markers in the markers array. New markers a visible on the map, but when zooming in/out the map suddenly the 'old' markers are visible again. So i have a mixture of the old and new markers.
Is this a Google Maps caching issue?
How to really remove the old markers from the map - map refreshing?
Thanks in advance.
SOLUTION
After writing this question i found the answer to this issue:
I also have an MarkerClusterer holding an reference to the markers array (and the markers). After clearing the MarkerClusterer all references to the old markers are gone. See this link:
Any change in zoom level causes all my markers to re-appear on my Google map
Try changing :
markers.length = 0;
markers = [];
to:
markers = [];
markers = null;
then just before adding the new markers initialize the array again.
Google Maps doesn't provide a way to break apart multiple markers that are at the same location. This can occur with a people or businesses at a multiple residency location such as an apartment building or professional services building. Depending at zoom level it can also occur at shopping malls, etc.
The way around that is to "spiderfy" them: when clicking on the first it breaks them out with a line to the location. This is done in Google Earth and George MacKerron wrote a package to do that for Google Maps. (https://github.com/jawj/OverlappingMarkerSpiderfier)
It can be integrated with markerclusterer, although it doesn't support marker clusterer's batch creation of markers.
My issue is that the application I'm working on wants to have specific icons for different types of activities. Spiderfier puts one of the markers on top. A person looking at the map has no way of knowing that there can be 10 or more other markers underneath the top marker.
Ideally, there would be a way to put a top marker that displays when there are multiple markers similar to the different icon in markercluster. It isn't a direct 1-to-1 since spiderfier also works when they are close but not exactly at the same location (default is 20 pixels) and markercluster has no provision for accessing multiple markers at the exact same location.
The ideal behavior would be have a special icon for spiders that broke into the spiderfied individual icons when clicked. Similar to markerclusterer, but without the zoom change and handling the same location. The special icon ideally would indicate how many other markers are at the spot, again like markerclusterer. The special icon could be hidden or become part of the spiderfied group.
Without some accommodation users would have no way of knowing multiple activities are at the location. They may even assume that the activity they want is not at that location because another activities marker is shown.
This is a plunker that has the problem: http://plnkr.co/edit/vimZNq?p=info
var markers = [];
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < 100; ++i) {
var latLng = new google.maps.LatLng(Math.floor(Math.random() * 10) / 10 + 39,
Math.floor(Math.random() * 10) / 10 - 100);
var marker = new google.maps.Marker({
position: latLng,
title: "marker " + i + " pos: " + latLng,
maxZoom: 8,
map: map
});
marker.desc = marker.getTitle();
bounds.extend(latLng);
markers.push(marker);
oms.addMarker(marker);
}
map.fitBounds(bounds);
var markerCluster = new MarkerClusterer(map, markers);
Thanks for your help,
David
Here's how I got it to work. Where map is a Gmap instance and oms is an Overlapping Marker Spiderfier instance. We're also using Marker Clusterer on the initial zoom which buys us a break.
map.addListener('zoom_changed', function() {
map.addListenerOnce('idle', function() {
// change spiderable markers to plus sign markers
// we are lucky here in that initial map is completely clustered
// for there is no init listener in oms :(
// so we swap on the first zoom/idle
// and subsequently any other zoom/idle
var spidered = oms.markersNearAnyOtherMarker();
for (var i = 0; i < spidered.length; i ++) {
// this was set when we created the markers
url = spidered[i].icon.url;
// code to manipulate your spidered icon url
};
});
});
oms.addListener('unspiderfy', function(markers) {
var spidered = markers;
for (var i = 0; i < spidered.length; i ++) {
url = spidered[i].icon.url;
// change it back
};
});
oms.addListener('click', function(marker) {
// put the clicked-on marker on top
// when oms un-spiders
marker.zIndex=999;
// set infowindow, panning etc.
});
I managed to match the following Versions:
MarkerClusterer 2.0.13
OverlappingMarkerSpiderfier 3.27
On every creation of a new Marker, i store the initialIconUrl in the Marker Object
var marker = new google.maps.Marker({
position: //some position
});
marker.setIcon(iconUrl);
marker.initialIconUrl = iconUrl;
When declaring the OverlappingMarkerSpiderfier, set the nearbyDistance to 0.001 (or some other very small value).
this.oms = new OverlappingMarkerSpiderfier(this.map, {
markersWontMove: true,
markersWontHide: true,
nearbyDistance: 0.001 //This will only spiderfy the Markers if they have the exact same position
});
Then, we need a listener on the maps 'idle' Event, to format the Markers manually.
I needed this because my SPIDERFIABLE Marker wouldn't show correctly on the first step, when transferring from the Clustered Marker to the seperate Markers.
var me = this;
google.maps.event.addListener(this.map, 'idle', function () {
me.oms.formatMarkers();
});
Listen to the oms 'format' Event and set the iconURL for Markers that are SPIDERFIABLE.
If the Marker is not spiderfiable, reset the Icon to the initial Url.
var spiderfiableIconUrl = //Whatever you need
this.oms.addListener('format', function (marker, status) {
var iconURL = status == OverlappingMarkerSpiderfier.markerStatus.SPIDERFIABLE
? spiderfiableIconUrl :
marker.initialIconUrl;
marker.setIcon(iconURL);
});
Hope this helps.
Some methods seems to be interesting like markersNearAnyOtherMarker but I cannot get it work.
An interesting way could be to use spiderfy and unspiderfy events and change marker when it's fired
overlappingMarkers = new OverlappingMarkerSpiderfier(map, overlapOptions);
overlappingMarkers.addListener('spiderfy', function (markers) {
markers.forEach(function (marker) {
marker.setLabel('*');
marker.setIcon(myNormalIcon);
})
})
overlappingMarkers.addListener('unspiderfy', function (markers) {
markers.forEach(function (marker) {
marker.setLabel(''+markers.length);
marker.setIcon(myOverlapIcon);
})
})
Unfortunatly, the unspiderfy event isn't fired until we open then close the overlap marker. If I find a conclusion to this solution I will update this post.
I am showing the tracking on map with marker points and line connecting them.
The problem is that i want to show the direction of travel on the links;
so I am not getting how to show the direction on the line between the marker points.
Is there any way to accomplish this task.
Showing the direction on the polyline can be accomplished with arrows.
There are some predefined paths that the google maps api3 provides.
See this section of the documentation -
SYMBOLS ON POLYLINE, that can be used other than an arrow.
Have a look at this fiddle that uses an arrow to indicate the direction on the polyline.
DEMO with a sigle symbol
You can also set the repeat property for the symbol so that it repeats for regular intervals.
DEMO with repeating symbols
JavaScript-
var iconsetngs = {
path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW
};
var polylineoptns = {
path: markers,
strokeOpacity: 0.8,
strokeWeight: 3,
map: map,
icons: [{
icon: iconsetngs,
offset: '100%'}]
};
polyline = new google.maps.Polyline(polylineoptns);
The interesting feature of this predefined symbol(the forward arrow specially) is that the arrow points towards the exact direction of which your co-ordinates are located. So, that obviously serves the purpose of denoting the direction in a Tracking System.
UPDATE: Not sure about the point you are trying to tell in the comments. The markers can be displayed the same way. Here is the code that adds markers with a loop and also set the polyline with arrows:
DEMO WITH MARKERS AND POLYLINE
Javascript:
var polylineoptns = {
strokeOpacity: 0.8,
strokeWeight: 3,
map: map,
icons: [{
repeat: '70px', //CHANGE THIS VALUE TO CHANGE THE DISTANCE BETWEEN ARROWS
icon: iconsetngs,
offset: '100%'}]
};
polyline = new google.maps.Polyline(polylineoptns);
var z = 0;
var path = [];
path[z] = polyline.getPath();
for (var i = 0; i < markers.length; i++) //LOOP TO DISPLAY THE MARKERS
{
var pos = markers[i];
var marker = new google.maps.Marker({
position: pos,
map: map
});
path[z].push(marker.getPosition()); //PUSH THE NEWLY CREATED MARKER'S POSITION TO THE PATH ARRAY
}
I have a Google Maps V3 polyline. I can detect click events on the entire polyline, but can I do anything more advanced with the click event?
What I'd like to do is detect which section of the polyline has been clicked, and show this in an alert.
routePath = new google.maps.Polyline({
path: routeCoordinates,
strokeColor: "#CC33FF",
strokeWeight: 3
});
routePath.setMap(map);
google.maps.event.addListener(routePath, 'click', function() {
alert(routePath);
// TODO: display which section of the polyline has been clicked?
});
Does anyone know how to do this in Google Maps?
thanks!
On the click event you can receive a LatLng of the coordinate that was clicked. However, since that will probably not be an exact point that is creating the polyline you need to find the closest point. You can use the computeDistanceBetween in the Google Maps library or you can use Pythagoras theorem as it should give you a good enough accuracy in this case.
You can find more information on computeDistanceBetween here:
https://developers.google.com/maps/documentation/javascript/reference#spherical
Here is a code example how you could do it with the computeDistanceBetween.
google.maps.event.addListener(routePath, 'click', function(h) {
var latlng=h.latLng;
alert(routePath);
var needle = {
minDistance: 9999999999, //silly high
index: -1,
latlng: null
};
routePath.getPath().forEach(function(routePoint, index){
var dist = google.maps.geometry.spherical.computeDistanceBetween(latlng, routePoint);
if (dist < needle.minDistance){
needle.minDistance = dist;
needle.index = index;
needle.latlng = routePoint;
}
});
// The closest point in the polyline
alert("Closest index: " + needle.index);
// The clicked point on the polyline
alert(latlng);
});
I ran into the same, issue here is how I dealt with it:
when setting up the handler:
google.maps.event.addListener(routePath, 'click', function(e) {
handlePolyClick(e, this)
});
var handlePolyClick(eventArgs, polyLine) {
// now you can access the polyLine
alert(polyLine.strokeColor);
});
Or if you want to access a related object set it by creating a variable on the polyLine:
routePath.car = $.extend({}, cars[1]); // shallow copy of cars[1]
then you can access your car from the event:
alert(this.car.color);
Finding the closest point by distance analysis will fail in a lot of cases where a path crosses back over or near itself.
You can use it to identify candidates, but you should confirm them by comparing the cross product and/or dot product of the 2 lines created if you use the click point to split 2 consecutive polyline points