javascriptjqueryjsonimagepreloading

getJSON issue with loading images across Safari and iOS


I'm trying to load a series of images that disappear at an interval of 300ms on page load.

The images are chosen at random from a JSON file, based on the users screen dimensions.

This works in Chrome but seems to fail randomly, and does not work at all in Safari (pauses on a random image) or on iOS (fails to load any images at all).

Here is my code:

// get the screen orientation based on css media query
var orientation = window.getComputedStyle(document.querySelector('body'), ':after').getPropertyValue('content').replace(/['"]+/g, '');

window.slides = [];

// function to randomise the order of an array
function shuffle(a) {
    var j, x, i;
    for (i = a.length - 1; i > 0; i--) {
        j = Math.floor(Math.random() * (i + 1));
        x = a[i];
        a[i] = a[j];
        a[j] = x;
    }
    return a;
}

$(document).ready(function() {
    $( 'html' ).addClass( 'js' ).removeClass( 'no-js' );

  // define the category and number of slides
  var imageDirs = { "lovers": 16 };

  // get slide urls from json file
  $.getJSON('slides/slides.json', function (data) {
    for (var thisDir in imageDirs) {
      var theseSlides = [];
      theseSlides = data[thisDir][orientation];
      shuffle(theseSlides)
      slides = theseSlides.slice(0, imageDirs[thisDir]);
    }
  })
  .done(function() {
    // randomise order of slides
    shuffle(slides);

    // have one blank slide at the beginning of the animation
    slides.push("initial-slide.png");

    if ( slides.length ) {
      for (var i = 0; i < slides.length; i++) {
        $('#wrapper').append('<img class="slide" src="slides/' + slides[i] + '">');
      }
    }
  });
});

$(window).on('load', function(){
  // wait for images to load before displaying animation
  $('#wrapper').waitForImages(true).done(function() {
    $('#preloader').remove();

    var currentSlides = [];

    $('.slide').each(function(){
      currentSlides.push($(this));
    });

    // remove slides at an interval of 300ms
    var timer = setInterval(function(){
      if (currentSlides.length){
        currentSlides.pop().remove();
      } else {
        clearInterval(timer);
      }
    }, 300);
  });
});

JSFiddle: https://jsfiddle.net/robertirish/6g41vwnL/59/

Live site: http://robertirish.com

Thanks in advance!


Solution

  • Thanks for the fiddle. Basically your problem is that in your load event the images haven't been appended to be the DOM yet. You can see this by logging currentSlides: https://jsfiddle.net/1fb3gczq/

    So, you need to ensure the DOM is ready before you manipulate it. I've moved your function to the ajax success which works in this case, but on slower connections you'll want to only run the effect once all the images have loaded in the DOM. Here's a working fiddle: https://jsfiddle.net/rcx3w48b/