0

I am loading images from my unsplash collection (https://unsplash.com/collections/3132360/dashboard) and changing the background image of the body (through CSS). It works, but there is a delay in the change. Is there a way I can preload the images and maybe even fade them in/out?

I have tried the new Image() of javascript, but that is for HTML images and not CSS.

Thanks in advance :)

Here is the jquery:

$('document').ready(function(){
  var x = 0;
  loadImage(x);
});

function loadImage(x) {
  x +=1;
  var image = 'https://source.unsplash.com/collection/3132360/1920x1080#'+x;

  setTimeout(function() {
    imgSwap(image, x);
  }, 30000)
}

function imgSwap(image, x){
  $('body').css('background-image', 'url(' + image + ')');
  loadImage(x);
}
Dom Needham
  • 69
  • 1
  • 14
  • You could load each image into its own div and show/hide the divs. Or maybe load ahead the next image while you show the current one. – peeebeee Sep 18 '18 at 14:06
  • why setTimeout have this big value "30000" ? – Bhagwan Parge Sep 18 '18 at 14:08
  • @peeebeee Problem is, the photo is randomised and so can't be loaded into divs.. I tried to load the image, giving the 30 second delay before swapping the image in the jquery but that doesn't work :( – Dom Needham Sep 18 '18 at 14:09
  • @bhagwanparge that was to try and preload the image into a variable for the change, which is every 30 seconds hence the 30000 :) – Dom Needham Sep 18 '18 at 14:09
  • @DomNeedham The browser will cache any images you load by using `new Image()`. You can then refer to them using `background-image` anywhere else in the page and they will load instantly. See [this SO answer](https://stackoverflow.com/a/10240297/2535504). To crossfade, you'll want to use two elements (probably a `div`). Your process should look something like this: `fade in image 1, load image 2 (hidden), delay, fade in image 2, load image 1.... and so on`. Hope that helps. – sheng Sep 18 '18 at 14:12
  • @ShengSlogar I have tried loading images that way, but this won't allow me to change them with CSS as I need to – Dom Needham Sep 18 '18 at 14:18
  • @DomNeedham I don't understand. The point would be loading an image with a `new Image()` to whatever path to cache (preload) that file in the browser. You'd then use an identical path to set your `.css({backgroundImage})` on whatever element you're loading that image into. Once `new Image()` has finished loading, any elements you update with `backgroundImage` will load that image immediately, from the cache. Does that make sense? – sheng Sep 18 '18 at 14:22
  • @ShengSlogar It makes sense yeah, but it doesn't work with my program. For some reason doing it this way won't make the background image update, but instead stays on the initial loaded image from the CSS.. – Dom Needham Sep 18 '18 at 14:25
  • @DomNeedham Can you post a code snippet? I can't help you if I don't know what issue you're having. – sheng Sep 18 '18 at 14:26
  • @ShengSlogar the codein the post is all there is. It updates the body background image through css. There is no image in the HTML, which is why I think the new Image() doesn't work for this. I have a feeling I will have to create a div for background images and update them through HTML to get the preloading to work. EDIT: sorry for probably not being very clear, I'm still very new to all of this :) – Dom Needham Sep 18 '18 at 14:31
  • @DomNeedham Please read through the SO answer I linked to earlier. Specifically: _Once images have been preloaded like this via javascript, the browser will have them in its cache and you can just refer to the normal URLs in other places (in your web pages) and the browser will fetch that URL from its cache rather than over the network._ Obviously you can solve this problem other ways, but in conjunction with `background-image` in CSS, it's your best shot. If you want to crossfade (i.e. two images), yes, you will need to use more than one element to achieve that. – sheng Sep 18 '18 at 14:35
  • @ShengSlogar I have just fixed the issue no. Changing the background url, I had to use image.src of the new Image() variable. If only using the variable as the url it never updated. Thank you for all of the help. – Dom Needham Sep 18 '18 at 14:38
  • @DomNeedham Ah, I didn't realize Unsplash was doing a redirect to the image. `image.src` is spot on. Glad you got that to work! – sheng Sep 18 '18 at 14:39

4 Answers4

1

You can add default image to body style in css to show the preload image.

body{
  background-image: url("http://www.ajaxload.info/cache/FF/FF/FF/00/00/00/5-1.gif");
  background-repeat: no-repeat;
}

https://jsfiddle.net/nimittshah/cwpdsnLy/

Nimitt Shah
  • 4,477
  • 2
  • 10
  • 21
0

This updated code now works, using img.src as the background URL for the CSS refreshes the image as needed. Using just the image variable as the URL does not.

$('document').ready(function(){
  var x = 0;
  loadImage(x);
});

function loadImage(x) {
  x +=1;
  var image = new Image()
  image.src = 'https://source.unsplash.com/collection/3132360/1920x1080#'+x;

  setTimeout(function() {
    imgSwap(image, x);
  }, 30000)
}

function imgSwap(image, x) {
  $('body').css('background-image', 'url(' + image.src + ')');
  loadImage(x);
}
Dom Needham
  • 69
  • 1
  • 14
-1

I think if you can include this following javascript code and css, it might be able to full fill what you want to achieve

function preloader() {
 if (document.getElementById) {
  document.getElementById("preload-01").style.background = "url(http://domain.tld/image-01.png) no-repeat -9999px -9999px";
  document.getElementById("preload-02").style.background = "url(http://domain.tld/image-02.png) no-repeat -9999px -9999px";
  document.getElementById("preload-03").style.background = "url(http://domain.tld/image-03.png) no-repeat -9999px -9999px";
 }
}
function addLoadEvent(func) {
 var oldonload = window.onload;
 if (typeof window.onload != 'function') {
  window.onload = func;
 } else {
  window.onload = function() {
   if (oldonload) {
    oldonload();
   }
   func();
  }
 }
}
addLoadEvent(preloader);
#preload-01 { background: url(http://domain.tld/image-01.png) no-repeat -9999px -9999px; }
#preload-02 { background: url(http://domain.tld/image-02.png) no-repeat -9999px -9999px; }
#preload-03 { background: url(http://domain.tld/image-03.png) no-repeat -9999px -9999px; }
  • Why are you using `window.onload`? OP is using `jQuery` and the `ready` function. Why are you checking for `document.getElementById`? This is supported in basically every single browser. See [Can I Use](https://caniuse.com/#search=getElementById). Finally, you can use the `backgroundImage` style prop so you don't have to repeat the rest of your styles. Still, overall I don't understand what your code is trying to accomplish. – sheng Sep 18 '18 at 14:25
  • What exactly you want to achieve – Shivam Sep 18 '18 at 14:25
  • Thank you for the help, I will try this solution later, although I'm not sure it will work as I don't have any images saved and can't access them in a chronological order like the code above tries to. – Dom Needham Sep 18 '18 at 14:26
-1

var x = 0;

$('document').ready(function(){  
  loadImage(x);
});

function loadImage(x) {  

  setInterval(function() {
  var randomId = new Date().getTime();
  var image = 'https://source.unsplash.com/collection/3132360/1920x1080#'+x+'?r='+randomId;
  
    console.log("x="+x + " " + image);
    imgSwap(image);
    x +=1;
  }, 30000)
  
  
}

function imgSwap(image){
  $('body').css('background-image', 'url(' + image + ')'); 
  
  //$('#bg_img').attr('src', image);
}
You can change value of x randomly, but i have found your img provider is not returning the images plz check this first, It is redirecting to some other url

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>

<!--<img id="bg_img" src="" width=400 height=400/>-->
Bhagwan Parge
  • 382
  • 1
  • 11
  • This does load the images better in terms of randomness so thank you! Doesn't fix the issue but I have done that now anyway (about to update the post) but still thank you ! :) – Dom Needham Sep 18 '18 at 14:40