Is there a way to check for markers whos icons intersect / overlap visibly? - leaflet

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.

Related

Setting the CRS for non-geographical svg map

I'm trying to show a custom non-geographical map with CRS.simple as explained here:
In a CRS.Simple, one horizontal map unit is mapped to one horizontal
pixel, and idem with vertical
However, I wish to use an SVG vector image as an overlay, but I don't get how the map unit is decided in this case, since the vector images don't really have a resolution?
Also, how could set the CRS origin's location to a specific point?
Thanks for helping

Getting the div screen location in Leaflet

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.

How can I fill color the tile leaflet?

This cite uses tiles from here, but in the initial state they are gray.
How can I fill tiles to make them look like in the example?
I use this code:
map = L.map('map', {zoomControl: false}).setView([..., ...], 15);
L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png"', {}).addTo(map);
Images:
needful:
original - light all:
There are a few approaches to this problem:
Search for a different tile provider which serves the desired colour scheme
Serve your own tiles after creating your own rendering style
Change the saturation of the tiles on the client side using 2d canvas
Substitute colours in the tiles on the client side using 2d canvas
Apply CSS colour filters to the tiles (by specifying a CSS class name for the tilelayer)
Change the saturation and substitute colours in the tiles on the client side using WebGL
The map at coinmap.org (the site mentioned in the question) uses a CSS filter (filter:saturate(4)) on all the tiles (on the CSS selector .map .leaflet-tile-pane)
You can use the ColorFilter plug-in with ['grayscale:100%'].
See some Demos.

How to control what markers are displayed by mapbox-gl-js

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.

Leaflet: How to display markers behind polygons?

I need icons (PNG) and polygons on my map. So I create icons as markers and polygons as polygons. Unfortunately regardless of creation order polygons are displayed "below" markers. I need is vice-versa. Is there a way, how to do it?
EDIT:
Correct default panes order in Leaflet 0.x: (from top-most to bottom-most)
objectsPane
popupPane
markerPane <= all markers icon (other than L.CircleMarker)
shadowPane <= all markers icon shadow
overlayPane <= all vectors (including L.CircleMarker)
tilePane
So just using the marker's icon shadow is not enough. You have to manually change the z-index of those panes in CSS (or through JS).
See also Leaflet: Polyline above Marker.
Original answer:
The stack order of vectors (like your polygons) and Markers is fixed in Leaflet 0.x. They are inserted into "panes" which order is (from top-most to bottom-most):
popupPane
markerPane <= all markers icon (other than L.CircleMarker)
overlayPane <= all vectors (including L.CircleMarker)
shadowPane <= all markers icon shadow
tilePane
So you should be able to easily workaround this fixed order by using the Marker's Icon shadow. If you still want the user to be able to click on your marker, simply use a transparent image for the normal icon, with the same size as your shadow image.
The situation is different in Leaflet 1.0. You can create your own panes (map.createPane), set their order by specifying their zIndex (possibly through CSS), and specify where your vectors and markers go by using their pane (and shadowPane for markers) option(s).