In my project I have around 50 overlay images to show on a Leaflet Map in sequence, using a slider. In order to avoid blanks, I am pre-loading the images in a loop:
imageArray.push(new imageItem(url+val));
Then, when I need to show the overlay layer, I have to send the image url to Leaflet:
ovl=new L.imageOverlay(get_ImageItemLocation(imageArray[k]), bounds),
ovl.addTo(mymap);
where get_ImageItemLocation()
is:
function get_ImageItemLocation(imageObj) {
return(imageObj.image_item.src)
}
I am wondering if this procedure is correct in terms of performances. Isn't there a way to send an Image object to L.imageOverlay instead of an url? Am I accessing twice the image with this?
In my project I have around 50 overlay images to show on a Leaflet Map in sequence, using a slider. In order to avoid blanks, I am pre-loading the images in a loop:
imageArray.push(new imageItem(url+val));
Then, when I need to show the overlay layer, I have to send the image url to Leaflet:
ovl=new L.imageOverlay(get_ImageItemLocation(imageArray[k]), bounds),
ovl.addTo(mymap);
where get_ImageItemLocation()
is:
function get_ImageItemLocation(imageObj) {
return(imageObj.image_item.src)
}
I am wondering if this procedure is correct in terms of performances. Isn't there a way to send an Image object to L.imageOverlay instead of an url? Am I accessing twice the image with this?
Share Improve this question asked Nov 3, 2017 at 9:59 Fabio MarzoccaFabio Marzocca 1,6771 gold badge19 silver badges41 bronze badges4 Answers
Reset to default 5If your images are cached in the browser (that depends mostly on headers sent by server), you are not downloading them twice. More on HTTP caching on MDN. The Network tab in DevTools is super useful for checking this:
Looking at the Leaflet docs and imageOverlay
source, it's clear it takes only URL, not the actual image data.
It wouldn't be too hard to change it, essentially just replace the code in their setUrl
method
this._image.src = url;
with something like
this._image.src = URL.createObjectURL(blob); // where blob is your image data
But… i wouldn't worry much about it. Just make sure your images are cached (with correct max-age
set in response header) in the browser and it will be okay.
Isn't there a way to send an Image object to L.imageOverlay instead of an url?
The Image Overlay API does not accept anything else than a string as of Leaflet 1.2.0.
Am I accessing twice the image with this?
You are creating an <img>
element twice with this. I do not think this would have a big performance impact, especially for 50 images only, and each pair having actually just one of the image being inserted into the DOM.
We could argue whether Leaflet Image Overlay should also accept an <img>
node instead of the url string. But you should realize that Leaflet internally applies classes and listeners on that <img>
element, so the node you pass in would be modified.
That may not be problematic for your case, but could be for other cases.
Finally, I am not sure there would be any big performance gain in doing so.
In fact, you could even get rid of your preloading <img>
reference (just keep a way to rebuild the URL, or keep the URL string in memory), since the only point is to make the browser start fetching the image and have it ready in cache.
Another approach, valid only if the overlays share the same bounding box, would be to put the 50 images together in a video file and use L.VideoOverlay
. Then, your slider would have to set the play time of the video to point to the correct frame, instead of switching images.
If you want to preload image in ImageOverlay
you can force loading image like this:
let imageLayer = L.imageOverlay(imageUrl, imageBounds)
imageLayer._initImage()
imageLayer.once('load', () => {
that.map.eachLayer(function (layer) {
that.map.removeLayer(layer);
});
imageLayer.addTo(that.map)
});
So you can call _initImage()
method on all of your overlays, add callbacks to them (to count ready overlays) and then use appropriate for your logic (show when all are ready or when first is ready). It depends on your needs.