I was trying to resize my custom icons when zooming in leaflet. I came up with two solutions for this. One using the L.Icon
tag, the other one using L.divIcon
. In both examples I only set 1 marker and group for readability
Method 1 using L.Icon: make groups with markers. Then on zoomend
i use mygroup.eachLayer(function (layer)
to change all icons for 1 layer using layer.setIcon()
. I repeat this for all groups
<script>
// Setting map options
....
// Setting Icon
var normalicon = L.icon({
iconUrl: 'icon1.jpg',
iconSize: [40,40],
iconAnchor: [20,20],
popupAnchor: [0,-20]
});
// Create a group
var normalLayer = L.layerGroup([
L.marker([200,200], {icon:normalicon})
]).addTo(map);
// Resizing on zoom
map.on('zoomend', function() {
// Normal icons
var normaliconresized = L.Icon.extend({
options: {
iconSize: [20*(map.getZoom()+2), 20*(map.getZoom()+2)], // New size!
iconAnchor: [20,20],
popupAnchor: [0,-20]
}
});
var normaliconchange = new normaliconresized({iconUrl: 'icon1.jpg'})
normalLayer.eachLayer(function (layer) {
layer.setIcon(normaliconchange);
});
.... Do the same for the other groups
});
</script>
Method 2 using L.divIcon: I make the icons and the different groups and add some CSS for each icon with a background-image
property. Then on zoomend
I simply use JQuery to change the css. background-size
css-property allows me to change the image size. I do this for each divIcon class I have
Css
.iconsdiv{
width:20px; height:20px;
background-image:url("icon2.jpg");
background-size: 20px 20px;
}
Script
<script>
// Setting map options
....
// Setting Icon
var divicon = L.divIcon({className: 'iconsdiv', iconSize: null }); // Explicitly set to null or you will default to 12x12
// Create a group
var divLayer = L.layerGroup([
L.marker([200,200], {icon:divicon})
]).addTo(map);
// Resizing on zoom
map.on('zoomend', function() {
var newzoom = '' + (20*(map.getZoom()+2)) +'px';
$('#map .iconsdiv').css({'width':newzoom,'height':newzoom,'background-size':newzoom + ' ' + newzoom});
... repeat for the other classes
});
</script>
I have barely any experience with javascript/jquery/...
Is the second option preferable as it does not require re-setting each icon? Would it improve performance when there is a large number of groups/icons?
I did a test myself using performance.now()
. I tested on a 1024x1180 (bounds) custom map. Once with 676 makers. Then with about half of this and lastly with 100 markers. The performance was measured inside the map.on('zoomend', function() {
function.
L.Icon
method to update. For the L.divIcon
this was only 10-30 milliseconds.L.Icon
took 300-400 milliseconds to update. L.divIcon
did the same in only 4-5 milliseconds.I also timed the performance of the initialization (L.layerGroup([...]).addTo(map)
) for 676 markers. L.Icon
took 2200-2400 milliseconds. L.divIcon
did the same in 80-95 milliseconds.
L.divIcon
clearly does a lot better (as expected). While it is a bit of a cheat, I guess I would prefer using this method. I can not directly think of reasons why the L.Icon
method would be preferred in case we want zooming
Edit:
I noticed that according to Leaflet Documentation 'Icon' you can also assign a className to the Icons. Using css-properties width
and height
the same can be done as I did earlier for the divIcons, thus saving you a lot of loading time, yet allowing you to use all options linked to L.Icon
. Your initialisation time will still be longer though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With