I am wondering if I can use the Leaflet OverlappingMarkerSpiderfier plugin with my circlemarkers.
I've loaded a GeoJSON file and added circlemarkers using;
var gj = L.geoJson(route, {
pointToLayer: function (feature, latlng) {
return L.circleMarker(latlng, geojsonMarkerOptions);
},
onEachFeature: onEachFeature,
}).addTo(map);
I followed the OverlappingMarkerSpiderfier example but I cannot understand how to combine my circlemarkers with the plugin.
I am guessing that changing;
pointToLayer: function (feature, latlng) {
return L.circleMarker(latlng, geojsonMarkerOptions);
}
to something like
oms.addMarker(marker);
(Leaflet OverlappingMarkerSpiderfier is a port of the original library for the Google Maps API)
Answer
OverlappingMarkerSpiderfier is a plugin designed for the L.Marker
class in Leaflet. Thus, it only accepts an L.Marker
object and can't handle L.circleMarker
properly, since it's based on the L.Circle
objects which is based on L.Path
. Credit for pointing this out goes to @FranceImage.
You can't use the L.circleMarker
layer with the spiderfier plugin, it will be glitchy (http://jsfiddle.net/GFarkas/qzdr2w73/). However, you can convert your GeoJSON data to traditional markers with the L.Marker
object. You can customize your marker icon to resemble to the circleMarker object (http://jsfiddle.net/GFarkas/qzdr2w73/4/).
To do this easily, Leaflet offers a L.DivIcon
style which can be customized with pure CSS, you won't need an image. To make orange circles with solid border in CSS, the code will look like the following:
.mydivicon{
width: 12px
height: 12px;
border-radius: 10px;
background: #ff7800;
border: 1px solid #000;
opacity: 0.85
}
The most important part is the border-radius
property. It will round your shape at the corners. To create a regular circle with it, you have to calculate the radius with the border. The formula is width / 2 + border * 4
if width = height
. After you created the CSS, you have to make a L.DivIcon
object to be used with L.Marker
:
var icon = new L.divIcon({className: 'mydivicon'});
When rendering the GeoJSON data to the map object, use L.Marker
instead of L.circleMarker
with the previously created icon:
pointToLayer: function (feature, latlng) {
return L.marker(latlng, {
icon: icon});
Now to use OverlappingMarkerSpiderfier properly: you have to create an OMS instance before adding the GeoJSON data:
var oms = new OverlappingMarkerSpiderfier(map);
After, you have to add each marker to the OMS object, so the built-in renderer can use them. To do this, use the onEachFeature
method of L.geoJson
:
onEachFeature: function (feature, latlng) {
oms.addMarker(latlng);
}
Finally, create an event associated with the OMS object and the markers it contains and add popup content to the markers. Note: if you don't add some markers to the OMS object, it won't apply the spiderfy effect on them. Also, the popup content in my case is in the GeoJSON data (properties -> popupContent).
var popup = new L.Popup();
oms.addListener('click', function(marker) {
popup.setContent(marker.feature.properties.popupContent);
popup.setLatLng(marker.getLatLng());
map.openPopup(popup);
});
Final note: markers created with L.DivIcon
will be rendered as individual div
objects instead of canvas or SVG. If you use a lot of points (around thousand or more) the rendering process will be painfully slow if the browser doesn't crash. To avoid it at masses of points like that, use OMS with other strategies (clusters, bounding box, etc.).
No comments:
Post a Comment