Leaflet marker on multiple layer - leaflet

I have created a leaflet map to display some data and now want to add a 'filter' to my map. I am using the grouped layer control plugin and have an issue which I cannot quite solve. For example I have 2 (or more) conditions which decide whether or not to show the marker and right now it works more like a OR filter, but i want a AND filter so that both (or more) conditions need to be checked in the overlay in order for the marker to be shown. If you have an idea or know about a post which already covered this issue, please let me know.
Code:
var berlin_1 = L.marker([52.48937,13.50341]).addTo(map);
//grouping
var A = L.layerGroup([berlin_1]);
var B = L.layerGroup ([berlin_1]);
//overlay
var groupedOverlays = {
"(headline1)": {
"condition 1": A,},
"(headline2)":{
"condition 2": B}};
L.control.groupedLayers(null, groupedOverlays).addTo(map);

Related

How can I add a class to leaflet layer groups?

I am making a game map with different layer groups. Everything works fine, but is it possible to add a class to the Layer groups as shown below?
The reason why is because I would like for example to place the second layer group on top of the first layer group. I know it is possible to add a class and then changing the z-index, but I have no idea how to do this.
This is how I have set up the Layer groups currently.
// Layer Groups
var lg_locat = L.layerGroup([locat_001, locat_002, locat_003,
locat_004]).addTo(map);
var lg_quests = L.layerGroup([quest_001, quest_002, quest_003,
quest_004, quest_005, quest_006, quest_007]).addTo(map);
var lg_noticeboards = L.layerGroup([noticeboard_001,
noticeboard_002, noticeboard_003]).addTo(map);
var lg_treasures = L.layerGroup([treasure_001, treasure_002,
treasure_003, treasure_004, treasure_005]).addTo(map);
Example of the map: http://www.droogjeproductions.nl/leaflet-map-test/index.html
You can call the setZIndex() method on the layer groupe which is setting the z-index of each layer of the layer group
For exemple if lg_noticeboards are above quests which are above treasures which are above locat :
var lg_locat = L.layerGroup([locat_001, locat_002, locat_003,
locat_004]).addTo(map).setZIndex(1);
var lg_quests = L.layerGroup([quest_001, quest_002, quest_003,
quest_004, quest_005, quest_006, quest_007]).addTo(map).setZIndex(3);
var lg_noticeboards = L.layerGroup([noticeboard_001,
noticeboard_002, noticeboard_003]).addTo(map).setZIndex(4);
var lg_treasures = L.layerGroup([treasure_001, treasure_002,
treasure_003, treasure_004, treasure_005]).addTo(map).setZIndex(2);
Something like that may work I think, if it doesn't try this:
lg_locat.setZIndex(1);
lg_quests.setZIndex(3);
lg_noticeboards.setZIndex(4);
lg_treasures.setZIndex(2);

Is there a way to have the layer checkboxes checked from the beginning on my leaflet map?

Im currently creating a map with leaflet and as the page loads all the checkboxes of my created layers are unchecked and im looking for a possibility to have them checked from the beginning, is there any way to do so?
Im a beginner when it comes to coding, did some research online and on the leaflet website but couldn't find any answer to my problem.
in the following code, the s0001 are my markers.
var BE = L.layerGroup([s0001]);
var GE = L.layerGroup([s0002]);
var ZH = L.layerGroup([s0003]);
var kantone = {
"Bern": BE,
"Genf": GE,
"Zürich": ZH,
};
L.control.layers(null, kantone).addTo(map);
Is this part of the code enough or do i need to put more of the code in my question?
Do i need to add/remove code or change up the code to make it work to have the checkboxes already checked as i load the page?
Many thanks in advance for your help and comprehension of me being a beginner !!
If you add some/all of the layerGroups to the map before you add the layers control, they will show up checked.
eg
var BE = L.layerGroup([s0001]).addTo(map);
var GE = L.layerGroup([s0002]).addTo(map);
var ZH = L.layerGroup([s0003]).addTo(map);
var kantone = {
"Bern": BE,
"Genf": GE,
"Zürich": ZH,
};
L.control.layers(null, kantone).addTo(map);

leafeltjs (mapbox) z-index ordering not working

Another developer created our original map but I'm tasked with making some changes. One of these is making sure the activated marker is brought to the front when clicked on (where it is partially overlapped by other markers).
The developers have used mapbox 2.2.2.
I have looked at leafletjs's docs, have followed some instructions on other posted solutions (e.g. solution one and solution two). Neither of these makes any difference.
Examining the marker in Chrome's console I can see the value of options.zIndexOffset is being set (10000 in my test case). I've even set _zIndex to an artificially high value and can see that reflected in the marker's data structure. But visually nothing is changing.
This is how the map is set up initially. All features are from a single geojson feed:
L.mapbox.accessToken = '<access token here>';
var map = L.mapbox.map('map', 'map.id', {
}).setView([37.8, -96], 3);
var jsonFeed, jsonFeedURL;
var featureLayer = L.mapbox.featureLayer()
.addTo(map)
.setFilter(function (f) {
return false;
});
$.getJSON(jsonFeedURL, function (json) {
jsonFeed = json;
jsonFeedOld = json;
// Load all the map features from our json file
featureLayer.setGeoJSON(jsonFeed);
}).done(function(e) {
// Once the json feed has loaded via AJAX, check to see if
// we should show a default view
mapControl.activateInitialItem();
});
Below is a snippet of how I had tried setting values to change the z-index. When a visual marker on the featureLayer is clicked, 'activateMarker' is called:
featureLayer.on('click', function (e) {
mapControl.activateMarker(e);
});
The GEOjson feed has urls for the icons to show, and the active marker icon is switched to an alternative version (which is also larger). When the active feature is a single Point I've tried to set values for the marker (lines commented out, some of the various things I've tried!)
activateMarker: function (e) {
var marker = e.layer;
var feature = e.layer.feature;
this.resetMarkers();
if (feature.properties.hasOwnProperty('icon')) {
feature.properties.icon['oldIcon'] = feature.properties.icon['iconUrl'];
feature.properties.icon['iconUrl'] = feature.properties.icon['iconActive'];
feature.properties.icon['oldIconSize'] = feature.properties.icon['iconSize'];
feature.properties.icon['iconSize'] = feature.properties.icon['iconSizeActive'];
}
if (feature.geometry.type == 'Point') {
marker.setZIndexOffset(10001);
marker.addTo(featureLayer);
}
//featureLayer.setGeoJSON(jsonFeed);
}
Any advice would be greatly appreciated! I'm at the point where I don't know what else to try (and that's saying something).
What probably happens is that you just flush your markers with the last call to .setGeoJSON():
If the layer already has features, they are replaced with the new features.
You correctly adjust the GeoJSON data related to your icon, so that when re-created, your featureLayer can use the new values to show a new icon (depending on how you configured featureLayer).
But anything you changed directly on the marker is lost, as the marker is removed and replaced by a new one, re-built from the GeoJSON data.
The "cleanest" way would probably be to avoid re-creating all features at every click.
Another way could be to also change something else in your GeoJSON data that tells featureLayer to build your new marker (through the pointToLayer option) with a different zIndexOffset option.

Leaflet - Adding Popups to GeoJSON point used in Multiple Toggle Layers

Using Leaflet, I am creating a map that has multiple toggle layers. Each layer is a combination of a GeoJSON line string and multiple points, where each point is used in multiple layers (Bus routes and all stops on the route). This is what I have so far (leaving out all the messy GeoJSON data):
var busStops = L.geoJson([busStop1, busStop2, busStop3, busStop4]);
var busRoute10 = L.geoJson([route10, busStop1, busStop3]);
var busRoute12 = L.geoJson([route12, busStop2, busStop4]);
var baseLayers = {
"Route 12": busRoute10,
"Route 12": busRoute12,
"All Bus Stops": busStops,
};
L.control.layers(null, baseLayers, {collapsed: false}).setPosition ('topright').addTo(map);
Works great. My problem is in binding a popup to each of the points so when you click on a bus stop the name pops up. I am using:
function onEachFeature(feature, layer) {
// does this feature have a property named popupContent?
if (feature.properties && feature.properties.popupContent) {
layer.bindPopup(feature.properties.popupContent);
}}
but I am struggling to figure out where to call it. The only thing that has worked is:
var busStops = L.geoJson([busStop1, busStop2, busStop3, busStop4],{
onEachFeature: onEachFeature});
var busRoute10 = L.geoJson([route10, busStop1, busStop3],{
onEachFeature: onEachFeature});
var busRoute12 = L.geoJson([route12, busStop2, busStop4],{
onEachFeature: onEachFeature});
That seems really, really redundant. Is there a better way to do this?
Indeed you may bind multiple times the same popup content to bus stops that appear in several GeoJSON groups… but in fact you are building multiple times your bus stops.
If those are default markers with shadow, you should see the shadow stacking up (i.e. the background should become darker) when you display lines buses which share the same stop.
Now if you want to avoid these multiple bus stops copies, that would require a more complex approach, as removing a busLine1 which has busStop1 will remove the latter from map, even if it is also part of busLine2 which is still on map…
Demo: https://jsfiddle.net/3v7hd2vx/52/

How to prevent overlapping pushpins at the same geolocation with Bing Maps?

If you have 2 pushpins on 'London' at the same geolocation, is there anything in the API to move them apart so they are both visible?
I can only find documentation on their old map points API which had PreventIconCollisions, this is what I want but can't see any reference to this in the new API.
I am using the JavaScript API.
So if I understand correctly, you have similar information on the same location, it this correct?
In order to display both information, you will have two options:
Merge information in the textbox using an appropriate way to present the information inside this ui element (using your own tabbed infobox for example)
Decluster the point manually when you're at a certain level of zoom
There is no default property to set this and it would really messy to do this on many pushpins, but in the main idea, you would have to: detect viewchangeend event, if you're at a certain level of zoom (or higher zoom level) then you're declustering them (I call it decluter nearby pushpins).
// Bind pushpin mouseover.
Microsoft.Maps.Events.addHandler(pin, 'mouseover', function (e) {
var currentPin = e.target;
currentPin.setOptions({ visible: false });
var currentLocation = currentPin.getLocation().clone();
var currentPoint = bmGlobals.geo.map.tryLocationToPixel(currentLocation);
if (currentPin.associatedCluster.length == 2) {
// Display the first pushpin
var pinA = createPin(currentPin.associatedCluster[0]);
var locA = bmGlobals.geo.map.tryPixelToLocation(new Microsoft.Maps.Point(currentPoint.x - pinA.getWidth(), currentPoint.y));
pinA.setLocation(locA);
bmGlobals.geo.layerClusteredPin.push(pinA);
// Display the second pushpin
var pinB = createPin(currentPin.associatedCluster[1]);
var locB = bmGlobals.geo.map.tryPixelToLocation(new Microsoft.Maps.Point(currentPoint.x + pinB.getWidth(), currentPoint.y));
pinB.setLocation(locB);
bmGlobals.geo.layerClusteredPin.push(pinB);
}
});
I will try to write a bing maps module about this, but in the fact, you'll have to get your clustered pushpins (or your own pushpin that has two associated data object) and then you will have to set their position based on the rendering on the client side.
I know this question is really old, but if someone is looking for something similar (clustering the pins) here is a good start: http://rtsinani.github.io/PinClusterer/