I have a situation with Leaflet, where I want to display different layers on a map and toggle between them using a layer controller.
My problem is that one of the layer is a geojson and I need to display the layers of that geojson in a specific order.
I do so using bringToFront and bringToback functions on the geojson layer.
But when I toggle between different layers using the controller, the ordering is lost.
Here is a fiddle showing the problem. Toggle the layers and the triangle will change color.
Question : is there a way to keep the layers order stable while toggling around ?
You could achieve the desired result, just by re-ordering your features in your geojson, without using Leaflet's bringToBack() method.
Higher position of an item in geojson.features array will result in higher display (above feaures with lower position).
The following function changes the order accordingly.
const moveLayersToBottom = (geojson, featureName) => {
geojson.features.sort((x, y) => (
x.properties.name === featureName ? -1 : y.properties.name === featureName ? 1 : 0
))
}
moveLayersToBottom(myGeojson, 'zone_1');
Here is your fiddle, edited (I commented out code of your fiddle that is unnecessary): https://jsfiddle.net/br0g962p/
Related
I'm trying to work out a variation on the mapbox code provided in this tutorial here: https://docs.mapbox.com/mapbox-gl-js/example/filter-markers-by-input/
But instead of filtering individual points, I'm trying to figure out how to filter polygons from a GeoJSON that have names appended based on an integer feature. Basically, I want to be able to enter the appended name of a polygon into a text box and have the map filter to just that polygon. I'm having difficulty identifying which parts of the code in the example to isolate and graft over. Has anyone tried something like this before?
When you say "filter to just that polygon", I think what you mean (in geospatial terms) is "filter to show only points within that polygon".
You will want to use Turf's "booleanWithin" function.
You will want to change this code:
layerIDs.forEach(function(layerID) {
map.setLayoutProperty(layerID, 'visibility',
layerID.indexOf(value) > -1 ? 'visible' : 'none');
});
You will have to iterate over the points themselves (not just their IDs), and use the booleanWithin function to check whether the point is within the polygon that you have somewhere else loaded.
I am building a map and want to use the leaflet markercluster plugin to cluster any markers that intersect visibly (the icons overlap each other). I can't seem to figure out a way to check whether the markers icons intersect though.
I've examined the documentation and the Marker objects. The marker object has no "bounds" object and has no function to return the bounds of the icon.
Yes, it's possible.
This is implemented in some Leaflet plugins, like Leaflet.LayerGroup.Collision - the technique involves fetching the computed style of each icon's HTML element to get the actual size in CSS pixels, offset those numbers by the relative pixel position of the marker's LatLng, and using a rtree data structure to speed up the calculation of the overlaps. Do have a look at the complete source for LayerGroup.Collision plugin.
Note that this technique only takes into account the rectangular bounding boxes of the icons; while it would be possible to check for the individual transparent pixels, that would involve more complex data structures and a different technique to fetch the opacity of each pixel.
I am working on a project using Leaflet. I want to place a label for objects on the map. I don’t want the label to appear on the map. I want the label placed above the map, but at the screen or div Left location from a latLng point.
I can’t seem to get the correct position using the functions available. Is there some example I can look at to give me insight? I would think Leaflet could do this.
The key here is to leverage the latLngToContainerPoint() method of L.Map - it will give you the pixel coordinates relative to the map container of the L.LatLng passed.
So create a container for a tick...
<div id="topbar"><span id="toptick">↓</span></div>
<div id="leaflet"></div>
...and use CSS to ensure it's on top of the map container, and has the same width. Then, run a function to translate the map point you want into an offset relative to the top-left corner of the map container...
function repositionEdges(){
var offset = map.latLngToContainerPoint(geopoint);
}
...run that after map initialization, and after every movement of the map...
repositionEdges();
map.on('move zoom', repositionEdges);
...and finally, inside that function, shift the tick horizontally tweaking its style...
function repositionEdges(){
var offset = map.latLngToContainerPoint(geopoint);
document.getElementById('toptick').style.left = offset.x + 'px';
}
You can see a working example at https://next.plnkr.co/edit/60qrWND50mCOQ11T?preview .
This is just one approach. The specific implementation will be different if you're using more than one point, or if you want to use <canvas> for drawing the ticks.
See also the graticule, edge scale bar and edge markers plugins from the Leaflet plugins list. Those plugins contain implementations of similar concepts.
I am loading a bunch of geojson points. I can see that I am loading about 40 points but which ones get displayed on my map seems random and somehow connected to the zoom level. Below you can see that only 2 points of ~40 are displayed.
What criteria does mapbox-gl-js use to decide what to display?
Is there a way to control what points are being displayed? (All of them? Some based on an attribute?)
This is likely occurring because you are using the default text-allow-overlap value of false. The text-allow-overlap documentation reads
If true, the text will be visible even if it collides with other previously drawn symbols.
Because your symbols overlap each other, some are hidden. You can disable this behavior by setting text-allow-overlap to true.
You might find marker clustering to be useful.
How can I deal with overlapping lines in the Leaflet map library?
I download geoJSON from the server sid and draw it right onto the map. If there are two identical entries, Leaflet draws them twice. This could be fixed by finding exact duplicated on the server side.
That however doesn't work for different datasets sharing some of the same space. As a result parts of both are drawn onto the same spot.
It appears that the lines are being rendered with the default Leaflet Polyline opacity of 0.5. If you were instantiating the Polylines yourself in code, you could override the opacity to make the lines opaque in this manner:
var myPolyLine = new L.Polyline( myPoints, { opacity: 1 } );
The line that would appear on top would then be the line that you added to the map last (one or the other is going to be on top, unless you make them both opaque and the same color). But this may be moot if you are loading in geoJSON directly and don't have control over how Leaflet renders it.