2

not very big on JS. I currently have a script I use to load/change background images every xxx seconds.

What I would like is to display an image and preload the next one so it displays seamlessly (ie: no jittering or slow loads).

Here is my current script, can this be adapted to achieve such a result?

<!-- Background Image Changer inpired by: https://stackoverflow.com/a/7265145 -->
var images = ['images/image01.jpg',
                'images/image02.jpg',
                'images/image03.jpg',
                'images/image04.jpg',
                'images/image05.jpg',
                'images/image06.jpg',
                'images/image07.jpg',
                'images/image08.jpg',
                'images/image09.jpg',
                'images/image10.jpg',
                'images/image11.jpg',
                'images/image12.jpg',
                'images/image13.jpg',
                'images/image14.jpg',
                'images/image15.jpg',
                'images/image16.jpg',];
var numSeconds = 30;
var curImage = 0;
function switchImage()
{
    curImage = (curImage + 1) % images.length
    document.body.style.backgroundImage = 'url(' + images[curImage] + ')'
}
window.setInterval(switchImage, numSeconds * 1000);

NOTES: There are 50 images in my script. I've only used fake named placeholders for clarity.

EDIT: To be clear, I only want one image displayed and the next (one) image to be preloaded. It's running on a RPi 3b so not much memory is available.

Yunnosch
  • 26,130
  • 9
  • 42
  • 54
RaSTuS
  • 23
  • 4
  • 2
    You might want to look at [Preloading images with JavaScript](https://stackoverflow.com/questions/3646036/preloading-images-with-javascript) – Wyck Mar 28 '22 at 13:22
  • Hint: just load all the images, then use CSS to hide/show them. You really don't need to load the image in the exact instant you show them. In this way, you can also put a transition :) – Christian Vincenzo Traina Mar 28 '22 at 13:22
  • 1
    Does this answer your question? [Preloading images with JavaScript](https://stackoverflow.com/questions/3646036/preloading-images-with-javascript) – Simone Rossaini Mar 28 '22 at 13:23
  • Please do not edit solution announcements into the question. Accept (i.e. click the "tick" next to it) one of the existing answer, if there are any. You can also create your own answer, and even accept it, if your solution is not yet covered by an existing answer. Compare https://stackoverflow.com/help/self-answer – Yunnosch Mar 28 '22 at 21:32

2 Answers2

1

I want to add a different answer here. There are a few options you can use to improve your web page performance. Using <link> with preconnect and preload rel value can helps you to load resources before using them:

Use preconnect keyword for the rel attribute to tell the browsers that the user is likely to need resources from this origin and therefore it can improve the user experience by preemptively initiating a connection to that origin.

<link rel="preconnect" href="<your-images-base-url">

Use preload keyword for the rel attribute to declare fetch requests in the HTML's , specifying resources that your page will need very soon. This ensures they are available earlier and are less likely to block the page's render, improving performance. Taken from https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload

Create preload link:

const preloadLink = document.createElement('link');
document.head.appendChild(preloadLink);
preloadLink.rel = 'preload';
preloadLink.as = 'image';

function preloadNextImage(href) {
  preloadLink.href = href;
}

function switchImage()
{
    curImage = (curImage + 1) % images.length
    document.body.style.backgroundImage = 'url(' + images[curImage] + ')';
    preloadNextImage(/* <next-image-url> */)
}
lissettdm
  • 12,267
  • 1
  • 18
  • 39
  • I've put all your functions at the top, and the url is the same I'm now posting is identical, but keep getting this error: The resource at “file:///home/....../var/www/html/images/image01.jpg” preloaded with link preload was not used within a few seconds. Make sure all attributes of the preload tag are set correctly. date-time-weather.html. Also added the fullpath to the document.body.style..... line. swapped them around so preload comes before loading, but no go. – RaSTuS Mar 28 '22 at 20:21
  • 1
    Excellent, got it, changed preloadLink.as = 'script'; to preloadLink.as = 'image'; and it worked fine. Thanks so much @lissettdm – RaSTuS Mar 28 '22 at 21:23
  • 1
    Glad is working now, I will change script by image, thank you for pointing that out. – lissettdm Mar 28 '22 at 22:42
0

You could just load the next image when displaying the current one using the JavaScript Image object. When switchImages runs again then the image will be already in the browsers cache. Also, the cached images are stored in a new array, so the cache "generator" will be ran only once. With this snippet you will need enough delay between iterations, so the next image will have enough time to be downloaded from the sever.

var images = ['images/image01.jpg',
                'images/image02.jpg',
                'images/image03.jpg',
                'images/image04.jpg',
                'images/image05.jpg',
                'images/image06.jpg',
                'images/image07.jpg',
                'images/image08.jpg',
                'images/image09.jpg',
                'images/image10.jpg',
                'images/image11.jpg',
                'images/image12.jpg',
                'images/image13.jpg',
                'images/image14.jpg',
                'images/image15.jpg',
                'images/image16.jpg',];
var numSeconds = 2;
var curImage = 0;
var cache = [];
function switchImage()
{
    curImage = (curImage + 1) % images.length;
    document.body.style.backgroundImage = 'url(' + images[curImage] + ')';
    if(images[curImage + 1] && !cache[curImage + 1]) {
      cache[curImage + 1] = new Image();
      cache[curImage + 1].src = images[curImage + 1];
    }
}
window.setInterval(switchImage, numSeconds * 1000);
muecas
  • 4,265
  • 1
  • 8
  • 18
  • Thanks but I don't want all images to be cached, I only want one image displayed and the next (one) image to be preloaded. It's running on a RPi 3b so not enough memory is available to be able to cache all images. – RaSTuS Mar 28 '22 at 15:04
  • @RaSTuS i don't think this script will impact memory usage. The next image is only loaded when the current one is displayed, so the entire image array is never loaded at the same time. Anyway the script could be modified to load just the second image. I found that maybe you need to move `curImage = (curImage + 1) % images.length;` after `document.body.style.backgroundImage = 'url(' + images[curImage] + ')';` to start by image with index 0, you script starts loading the image a the second position of the array. – muecas Mar 29 '22 at 17:25