I'm using Leaflet JS to build my maps, but I'm having a few issues selecting layers.
I'm aiming to fit my map to a polygon. Leaflet generates a Leaflet ID for each element on the map, but these IDs are random. So I want to create an array which links each Leaflet ID with a known polygon ID.
The concept comes from here How to interact with leaflet marker layer from outside the map? but I'm unsure how to implement it.
The object 'map._layers' stores all the elements including the ID of each polygon. So I'm looping through it as follows:
var idstore = [];
for (var x in map._layers) {
// here idstore[x['polyid']] = x;
}
Now I can use that array to associate my polygon IDs to Leaflet IDs. The resulting array should be as follows:
array('polygonid'=>'leafletid','155447'=>'478','748745' => 479);
My problem is the loop isn't working correctly. I can only see the first 2 records coming up which are actually overlays (map tiles). The elements are definitely in that object though.
What am I doing wrong?
A good first step would be looking through the Leaflet reference documentation and using the documented .eachLayer function instead of a for loop on a private variable.
var idstore = [];
map.eachLayer(function(layer){
// ...
});
Related
In Bing Maps v7 I was able to add pushpins to an entityCollection and then loop through that collection later in the code to set options or whatever. Now, I am having trouble getting pins from the v8 layers.
Here is what I used to do in v7 after I had already added the pin to the entityCollection:
for (var i = 0; i < entityCollection.getLength() ; i++) {
var pin = entityCollection.get(i);
pin.setOptions({ visible: true });
}
I have changed the object entityCollection to a layer for v8 and I am also looping through the layer while i < entityCollection.data.length
Now, in Bing Maps v8, I'm having trouble getting the pin object from the layer that I have already added it to. The code above throws an error on the setOptions line and I have also tried getting the pin with:
entityCollection.data[i]
instead of
entityCollection.get(i)
But that doesn't work either. I'm afraid my question is too generic, because I can't find anything that actually answers my question. I have a work around, but that causes failures later when I want to hide all the pins with certain attributes. Thanks in advance!
Bing Maps v8 has done away with the entityCollection - though they say it's still sort of supported, you obviously don't want to be using deprecated things any more.
Anywhere you have an entityCollection, replace it with a Layer (Microsoft.Maps.Layer). Layers expose the getPrimitives() method which will provide you with an array of the contents.
var map = new Microsoft.Maps.Map(..., ...);
var layer = new Microsoft.Maps.Layer();
// Add layer data...
layer.add(new Microsoft.Maps.Pushpin(...));
// Add layer to map
map.layers.insert(layer);
// Then you can iterate
var layerItems = layer.getPrimitives();
var len = layerItems.length;
for(var i = 0; i < len; i++){
var pin = layerItems[i];
// Do something with your pin
pin.setOptions({visible: false});
}
Note that if you're doing mass updates to the entire contents of the layer, such as showing or hiding every pin in the layer, you can do that directly on the layer. This will save you (the browser) a chunk of work setting each pin individually.
layer.setVisible(true);
Yes, in V8 layers have a getPrimitives function which returns an array containing all the shapes. You can then loop through these shapes like you would any other array.
This is somewhat similar to the question asked here --
I'm writing a search box for a map application, which retrieves a whole set of search results (people's names & info) at once from a server and then pages through the list of results. So at any given point on the map there are two kinds of markers -- a background marker for points which are in the search results but not in the current page, and a foreground marker for points which are in the current page of search results.
All this works nicely.. what I'd like to do now is set it up so that if a user zooms or pans the map, the search results list updates to show only markers within the current map bounds.
Obviously there are server-side ways to do this, or I could also just run through the whole list of markers to see which fit within the current bounds; but does anybody know a built-in way to do this within leaflet? Something which would look like map.getVisibleLayers()?
I think this may be of help:
https://github.com/stefanocudini/leaflet-list-markers
as you can see from the demo, including all markers in a layer, this plugin shows a list of only those visible in the current viewport.
Its usage is simple, in a row:
var markersLayer = new L.LayerGroup();
map.addControl( new L.Control.ListMarkers({layer: markersLayer}) );
The code for obtain it is like as:
var layers = L.LayerGroup(), //layers contains all markers..
contained = []; //makers in map boundingbox
layers.eachLayer(function(l) {
if( l instanceof L.Marker && map.getBounds().contains(l.getLatLng()) )
contained.push(l);
});
Here's a fully working function that does the job:
// var map is an instance of a Leaflet map
// this function assumes you have added markers as GeoJSON to the map
// it will return an array of all features currently shown in the
// active bounding region.
function getFeaturesInView() {
var features = [];
map.eachLayer( function(layer) {
if(layer instanceof L.Marker) {
if(map.getBounds().contains(layer.getLatLng())) {
features.push(layer.feature);
}
}
});
return features;
}
You have to check the bounds of each layer versus the map's bounds. Because eachLayer() returns all layers regardless of whether they are in the visible extent.
if(map.getBounds().contains(layer.getLatLng())) { ... }
In Stefano's code, this is shown around this line:
https://github.com/stefanocudini/leaflet-list-markers/blob/master/src/leaflet-list-markers.js#L95
Regarding the last part of your question, if you want to iterate through visible layers, you can use eachLayer, e.g:
map.eachLayer(function (layer) {
// do something with the layer
});
API reference: http://leafletjs.com/reference.html#map-stuff-methods
I am displaying two different leaflet maps in the same page. After a certain event. I want a Polyline to appear on both of them. I would like to avoid, if possible, to create a copy and keep two different variables.
I am trying yo use the following:
var line_coordinates = [[1,2],[3,4]];
var my_polyline = L.polyline(line_coordinates);
my_polyline.addTo(map1);
my_polyline.addTo(map2);
However, if I run the above code, the Polyline will be displayed only on the map2.
Afterwords, I will need to change again its coordinates to some new_line_coordinates, and I will run the following:
my_polyline.setLatLngs(new_line_coordinates);
my_polyline.redraw();
The polyline should now appear updated to the new coordinates. However, again, it appears only on map2.
What am I doing wrong? Is it possible to achieve what I am trying to do?
As geocodezip mentioned in a comment, adding a polyline to a map sets the polyline object's this._map instance variable. Therefore, there is no way to have the object rendered on both maps with the way in which it is currently implemented.
You can view the relevant source code here.
You can't add the same layer to multiple Leaflet maps. But I had a similar problem using a more complex GeoJSON layergroup and ultimately solved it by getting the GeoJSON object from the layer using toGeoJSON() and using it to create a new layer for the second map. For a simple polyline, you could use getLatLngs(). So:
var line_coordinates = [[1,2],[3,4]];
var my_polyline = L.polyline(line_coordinates);
my_polyline.addTo(map1);
var new_polyline = L.polyline(line_coordinates);
new_polyline.addTo(map2);
should work, as would:
var line_coordinates = [[1,2],[3,4]];
var my_polyline = L.polyline(line_coordinates);
my_polyline.addTo(map1);
var my_polyline_latlngs = my_polyline.getLatLngs();
var new_polyline = L.polyline(my_polyline_latlngs);
new_polyline.addTo(map2);
i need some help with google map api v3 markers.
I got an array which contains coordinates i retrieve from a file. I am trying to traverse the array, and plot them using the markers.
Traversing the array to retrieve the coordinates is not a problem, however, when i start using the coordinates to plot on google map. i realise that i am getting (NaN, NaN) as the coordinates.. Because of this, i am not able to do the plotting.. any idea why isit? Thanksss
my codes so far:
var temp = new google.maps.LatLng(myObject[o]);
retrieverouteMarker(temp);
The constructor for LatLng takes two arguments (the latitude and longitude of the point), so this line is clearly wrong:
var temp = new google.maps.LatLng(myObject[o]);
Of course, since we have to idea what myObject is, or what the function retrieverouteMarker does, there isn't much more we can do to help.
I currently have a implementation where some markers coming from JSON list is shown, on a particular area, Now I want to filter these marker depending upon some criteria, I have done the filtering part, and got the filtered list. Now to render this markers on the map again, The current implementation loads the js with a key again, also creates the GMap2 object and draws the list of marker on the newly created map, which is really annoying. I want map to be there and only markers to be added and removed from the map.
Any help is appreciated
You can use addOverlay and removeOverlay to add/remove markers from an already displayed map. See the examples here: http://code.google.com/apis/maps/documentation/overlays.html#Markers
var latlng = new GLatLng(lat, lng);
map.addOverlay(new GMarker(latlng));
You can make drawMap() and drawMarkers() as two separate functions. And after map has been created redefine drawMap to empty function like this:
drawMap = function(){}; After that only drawMarkers() will be executed.
Hope this is what you need. If not, provide some code.