Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to preload SVG image tags?

Tags:

caching

svg

d3.js

I'm building an SVG-based visualization that (partially) relies on showing many images in quick succession. The images can't be fetched fast enough from the network, so they must be preloaded.

My understanding is that SVG doesn't properly cache image tags, at least in major browsers. So JavaScript preloading librairies and techniques (eg. this SO question) won't work. (I could resort to using layered HTML img tags, but because of the specifics of my application, I would like to stick to pure SVG as much as possible)

I see two options:

  • Encoding the PNG image data as base64, storing it in memory as strings and using the strings to iteratively populate image tags using data:image/png;base64.
  • Layering many SVG groups on top of each other with all but one set to display: none or visibility: hidden and iteratively unhiding the appropriate group. However, I believe it won't be possible to programatically detect that all images have finished preloading.

What's the best way to preload the image data? Perhaps I've missed an easier option.

like image 412
David Chouinard Avatar asked Jun 08 '13 15:06

David Chouinard


1 Answers

I'm not familiar enough with the underlying mechanics of web browsers to know if this will work with svg image tags, but I had success caching images with new Image():

    //download low quality images
    var imageArray = []
    for (var i = 0; i < 600; i++){
        imageArray[i] = new Image();
        imageArray[i].src = moviePath + (i + 1) + '.jpg.t';
        imageArray[i].onload = function(){
            var i = this.src.split(movieName + '/')[1].split(".")[0];
            d3.select("#bar" + i).style("stroke", 'rgb(' + colors[i].rgb + ')');
        }
    }

To show an image, I just set the src of the displayed image to one that was already loaded and the browser loads it from its cache.

There is another small trick used later in the source - show a low quality image first and starting loading a high quality one only after a short timeout passes without another image being selected. Then, after the high quality image has loaded, show it only if the same image is still selected.

No idea if these are best practices or anything, but it worked reasonably well.

like image 169
Adam Pearce Avatar answered Oct 05 '22 17:10

Adam Pearce