Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preloading SVG images

I have about a hundred of simple SVG images, which are stored in about five different image folders. Currently, when they are needed to be displayed, they are retrieved right then. This, for the most part, works, but it does sometimes cause flickering, which I would like to eliminate. Is there a way to preload these images prior to when they are needed, so that they would be cached? I've seen some solutions on here, but they mainly deal with a small number of images. Is there a preferred way of doing a high volume preload?

Thanks!

like image 424
jldavis76 Avatar asked May 29 '15 18:05

jldavis76


People also ask

What is image preloading?

Preload lets you tell the browser about critical resources that you want to load as soon as possible, before they are discovered in HTML. This is especially useful for resources that are not easily discoverable, such as fonts included in stylesheets, background images, or resources loaded from a script.

Why are my svgs fuzzy?

SVG coordinates are mapped to the left of screen pixels and not in the middle, as illustrated above. Therefore, when you try to draw a single pixel line at (2, 1), your line will be drawn on half pixels resulting in blurred or anti aliased line.

Do SVG images load faster?

Irrespective of image count, the page with SVG images is still the fastest at 0.75s, with PNG @1X, it takes about 1.0s, about 33% slower. For PNG @2X, loading time is 1.5s, again 200% slower when compared against SVG.

How does Preload work?

<link rel="preload"> tells the browser to download and cache a resource (like a script or a stylesheet) as soon as possible. It's helpful when you need that resource a few seconds after loading the page, and you want to speed it up. The browser doesn't do anything with the resource after downloading it.


1 Answers

If you have all the URLs of the images you can start to cache them as soon as possible in a JS object using the url, and later just fetch them from there when you need them.

In your page you may have the list of SVG images stored in somewhere, but at the end what you need is just a JS array of URLs string.

Here's a quick example:

// assuming you've gotten the urls from somewhere and put them in a JS array
var urls = ['url_image_1.svg', 'url_image_2.svg', ... ];

var svgCache = {};

function loaded(){
  // just increment the counter if there are still images pending...
  if(counter++ >= total){
    // this function will be called when everything is loaded
    // e.g. you can set a flag to say "I've got all the images now"
    alldone();
  }
}

var counter = 0;
var total = urls.length;

// This will load the images in parallel:
// In most browsers you can have between 4 to 6 parallel requests
// IE7/8 can only do 2 requests in parallel per time
for( var i=0; i < total; i++){
  var img = new Image();
  // When done call the function "loaded"
  img.onload = loaded;
  // cache it
  svgCache[urls[i]] = img;
  img.src = urls[i];
}

function alldone(){
  // from this point on you can use the cache to serve the images
  ...
  // say you want to load only the first image
  showImage('url_image_1.svg', 'imageDivId');
}

// basically every time you want to load a different image just use this function
function showImage(url, id){
  // get the image referenced by the given url
  var cached = svgCache[url];
  // and append it to the element with the given id
  document.getElementById(id).appendChild(cached);
}

Note:

  • Consider also the case of error on loading the image, so put a callback also to img.onerror and serve in case some "missing" image as replacement
  • There are some more considerations to do here, like some browser quirks with SVGs but the basic solution should work.
like image 51
MarcoL Avatar answered Oct 02 '22 21:10

MarcoL