mdinger
mdinger

Reputation: 85

Swap an image without flicker while showing the new one immediately

TL;DR: Is there a way to swap the images reliably while showing whichever image is being loaded at the time without causing page flicker?


I have 2 images and 2 buttons and when I hover over one button it shows the one image. Hovering over the other button swaps to the second image. I was doing it like this:

$('#button1').mouseover(function() {
    $('#image').attr('src', 'image1.png');
});

$('#button2').mouseover(function() {
    $('#image').attr('src', 'image2.png');
});

This works fine but when the first image has loaded and the second hasn't, it doesn't show the second image until it has completed loading. To try to give the user some indication of when the new image is loading (which they're expecting to appear immediately), I forced it to add a null image before these swaps, like this:

$('#button1').mouseover(function() {
    $('#image').attr('src', '#');
    $('#image').attr('src', 'image1.png');
});

$('#button2').mouseover(function() {
    $('#image').attr('src', '#');
    $('#image').attr('src', 'image2.png');
});

This works great when one image is loading by showing the image as it's loading but now once both are loaded, the null image in between them causes a flicker when switching images. I thought I could fix this by turning the null image off once both images are loaded but that has turned out to be unreliable. Both $('#image').prop('complete') and imagesloaded as suggested in other locations on stackoverflow are inconsistent at noticing whether the image has been loaded or not. Detecting loaded images just seems to be a dead end.

I also considered trying to force the images to show and hide before and after they were created but this doesn't seem to work at all though I'm not sure why. The new one doesn't show while loading and I'm not sure if they're swapping properly:

$('#button1').mouseover(function() {
    $('#image').hide();
    $('#image').attr('src', 'image1.png');
    $('#image').show();
});

$('#button2').mouseover(function() {
    $('#image').hide();
    $('#image').attr('src', 'image2.png');
    $('#image').show();
});

Is there a way to swap the images reliably while showing whichever image is being loaded at the time without causing page flicker that I haven't tried?

Upvotes: 0

Views: 3125

Answers (4)

mdinger
mdinger

Reputation: 85

The problem is having this HTML content updated by changing the src location makes the browser wait until the image is loaded before displaying the image. This doesn't seem to be modifiable.

The HTML:

<img id="image" src="">

and javascript with this behavior:

$('#button1').mouseover(function() {
    $('#image').attr('src', 'image1.png');
});

$('#button2').mouseover(function() {
    $('#image').attr('src', 'image2.png');
});

Changing the HTML:

<div id='image_container'> </div>

and javascript to:

$('#button1').mouseover(function() {
    // Remove the old image and replace it with the new one
    $('#image_container').empty()
                         .append("<img id='image' src='image1.png'>");

});

$('#button2').mouseover(function() {
    $('#image_container').empty()
                         .append("<img id='image' src='image2.png'>");
});

makes the browser show the image while it is downloaded. I'm not exactly sure why but it seems to just be that new <img>s are handled differently than <img>s with src modifications.

Upvotes: 0

Leviscus Tempris
Leviscus Tempris

Reputation: 140

Try this:

var preloadImages = ['image1.png', 'image2.png'];
$('#button1').mouseover(function() {
    $('#image').attr('src', preloadImages[0]);
});

$('#button2').mouseover(function() {
    $('#image').attr('src', preloadImages[1]);
});

Upvotes: 0

Jordan Coil
Jordan Coil

Reputation: 35

Try storing the sources of the image into JavaScript variables, and use those variables to swap the image sources.

This might avoid the loading, not sure, but it might.

Upvotes: 0

Gregg Duncan
Gregg Duncan

Reputation: 2725

What you're wanting to do is preload the images so that they are cached in the browser. then there's no delay on your mouse over. Here's a jquery plugin to cache the images and a call for them.

$.fn.preload = function() {
    this.each(function(){
        $('<img/>')[0].src = this;
    });
}

// Usage:

$(['image1.png','image2.png']).preload();

This is not my code: credit to James @ Preloading images with jQuery

Upvotes: 3

Related Questions