Skip to content Skip to sidebar Skip to footer

Flicker On Jquery Background Change

I created a jsfiddle for my current code. http://jsfiddle.net/gL5sB/38/ I am trying to change the body background css on scroll event. When the background changes it appears to fli

Solution 1:

Why don't you use one image (sprite image) and just move it with background-position instead of replacing the image? (about the size - you can set percentage based background-size in your case - the height will be 1400%

Because your'e preloading all the images anyway - it won't cost you in page loading time - and it might also save some time because with the right compression 1 image of 14 will weight less then 14 images of 1

Solution 2:

Chrome is OK. I can see the flicker in IE. A Solution for that is at the bottom of this post.

I suspect A video version would compress and load faster than all the images, but as suggested by @Allendar drawing it would be the most transmission efficient. I would suggest canvas or SVG.

Another way using images along would be to have individual components as either images or icon fonts placed on the display with absolute positioning and then just turning them on or off in script. But that's a very complex solution.

I think the simplest and fastest method for you to solve the issue today though would be to just tweak the solution you have. As other people have suggested, the multiple images approach won't be super efficient and if you're going to take that route at least make sure you set the caching headers on your web server to cache indefinitely;

Cache-Control:public;Expires:Mon,31Dec2035 12:00:00 GMT

OK, so the flicker problem is just a bug/inefficiency in the rendering engine in IE, so here's a workaround that uses a different approach.

Basically stretch an absolutely positioned DIV over the body, instead of using the body itself. In fact, in this case we use multiple DIVs, one for each image and overlay them on top of one another. You could create these nodes in script as well.

Secondly, add another DIV for your content, and overlay that over the body as well;

<body><divid="b100"class="background"style="background-image:url('http://ingodwetrustthemovie.com/bgImage/100.jpg')"></div><!-- rest omitted --><divid="b113"class="background"style="background-image:url('http://ingodwetrustthemovie.com/bgImage/113.jpg')"></div><divid="content"><divid="test">test div</div>
        here is some text
    </div></body>

The simply show one at a time and hide the rest;

functionswitchImage() {
    var s = $(window).scrollTop()/10;
    var index = Math.floor(s / 5);

    $('.background').hide();
    $('.background').eq(index).show();
}

I had a suspicion that twiddling the css display option would be less flickery than changing the src attribute and it seems to do the trick.

Here's the Fiddle

Of course you may still need to optimise the code to allow for the first loaded image to be shown first instead of the plain background, but I think this demonstrates the principle of a fix.

You could also consider making a very large CSS Sprite, by bundling the images into one huge strip and then using background-position. That would probably work on the body tag itself then. Of course this would mean downloading a huge file before you can display any images at all, but there are two advantages;

  1. One image (especially with such similarity) will compress way better than each individual one in isolation.
  2. Using the same caching directives, that's only one HTTP/GET/302 cycle instead of 13 once you've fetched the image the first time, so your page may load faster still.

SVG

SVG elements work much like the DOM. If you can get your content delivered as an SVG you can drill into the graphic, locate the elements, give them IDs etc, and manipulate them much like you would any other DOM element;

<svgxmlns="http://www.w3.org/2000/svg"version="1.1"><ellipseid="e1"cy="420"cx="200"rx="420"ry="30"style="fill:3f5566" /><ellipseid="e2"cy="420"cx="170"rx="390"ry="20"style="fill:4f5566" /><ellipseid="e3"cy="420"cx="145"rx="370"ry="15"style="fill:5f5566" /><ellipseid="e4"cy="420"cx="100"rx="370"ry="20"style="fill:6f5566" /><ellipseid="e5"cy="420"cx="45"rx="300"ry="15"style="fill:8f5566" /></svg>

Here's another fiddle that hides/unhides SVG elements based on a scroll.

Ideally, assuming they've generated that graphic in 'layers', try and have your designers deliver you an SVG where the layers are converted into groups. Adobe Illustrator can do that for instance.

Then you can easily turn off the layers/groups as necessary to create the animated effect.

Solution 3:

Here is a solution that works (2014.7.11) at firefox 30.0, chrome 35.0, opera 22.0, ie 11.0:

STEP 1: add these lines at .htaccess:

# cache for images
<FilesMatch "\.(png)$">
Header set Cache-Control "max-age=10000, public"
</FilesMatch>

STEP 2: add images preloading, for example:

var pics = []; // CREATE PICS ARRAY

$(document).ready(function(){
    ...
    preload(
        '/public/images/stars.red.1.star.png',
        '/public/images/stars.red.2.star.png',
        '/public/images/stars.red.3.star.png',
        '/public/images/stars.red.4.star.png',
        '/public/images/stars.red.5.star.png',
        '/public/images/stars.empty.png'
    );
    ...
    $('.rating').on('mousemove', function(event){
        var x = event.pageX - this.offsetLeft;
        var id = getIdByCoord(x); //if ($(this).data('current-image') != id) {
            $(this).css('background-image', 'url(' + pics[id].src + ')');
            $(this).data('current-image', id);
        }
    })
    ...
})

...

// PRELOAD FUNCTION TO SET UP PICS ARRAY IN MEMORY USING IMAGE OBJECTfunctionpreload() {
    for (i = 0; i < arguments.length; i++) {
        pics[i] = newImage();
        pics[i].src = arguments[i];
        // alert("preload " + arguments[i]);
    }
}

P.S. thanks Shawn Altman

Post a Comment for "Flicker On Jquery Background Change"