Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Synchronously test if image(s) is loaded? #122

Closed
nybblr opened this issue Jan 22, 2014 · 4 comments
Closed

Synchronously test if image(s) is loaded? #122

nybblr opened this issue Jan 22, 2014 · 4 comments
Labels

Comments

@nybblr
Copy link

nybblr commented Jan 22, 2014

I am using this plugin to show a loading animation for images in a slideshow: before fading to the next slide, I use imagesLoaded.done() on the particular slide.

Before creating the callback, I first show the loader. The done() callback hides it.

This works great when the next image in the slideshow is downloading: the loader shows and hides itself appropriately. However, once the images are already loaded, the loader "flickers" between slides because it is being shown, then immediately hidden in the done() callback. Since the callback isn't executed synchronously, the DOM has a chance to rerender before hiding the loader.

The resulting effect is an irritating flicker between every single slide. So it'd be nice to take advantage of the LoadingImage.prototype.check method to check if an image is already loaded (or failed to load) without handing the thread back to the browser for a rerender. Then I could check if the image is loaded before even showing the loader (and thus prevent the flicker altogether).

I know this can usually be done with .complete on the image node, but to my knowledge this has some compatibility issues; is this cross-browser logic already implemented in imagesLoaded? Could it be exposed for use?

Or, maybe an option could be passed in which makes imagesLoaded trigger the callbacks immediately (without giving up the main thread) if the image is loaded?

~ Jonathan

@desandro
Copy link
Owner

Hi there! Thanks for going over your use case. I appreciate the walk through, but is there a simplified test case I could take a look at? Use the CodePen to get you started.

I'm not sure if this is what you're getting at, but the async checking is a hack I originally added, to allow users to bind an event before the checking began. I could add an option, so that checking is done immediately.

var imgLoad = new imagesLoaded( imgs, {
  // disable checking immediately to bind event
  isInitChecking: false
});
// bind
imgLoad.on( 'always', function(){...});
// ready for checking
imgLoad.check()

While I'd like to remove this hack, my hesitation is that this breaks backwards compatibility.

@nybblr
Copy link
Author

nybblr commented Jan 27, 2014

I could try to throw something together, but I think it only shows up with complicated pages (e.g. with transitions), otherwise the callback is executed almost immediately.

I'm not sure that would quite solve the problem, here's a code sample similar to what I have:

// When the page loads, the spinner is hidden.
// At some point after the page is loaded (say via the console, 10 seconds after loading), I run this:

showSpinner();
$("img.img-1").imagesLoaded()
  .done(function () {
    hideSpinner();
  });

In many cases, when that code is run the image is already fully loaded, so ideally the spinner would never show (or "flicker"). However, that bit of code seems to be similar to:

showSpinner();
setTimeout(function () {
  hideSpinner();
}, 1);

Thus, the spinner is shown for a while because the hideSpinner callback isn't called until after some page rerendering has occurred. For complex pages with lots of animations, this can be around a tenth of a second.

So two solutions could alleviate this flicker: I could do a synchronous check to see if the image is loaded (immediate boolean returned):

if ( $("img.img-1").hasNotFullyLoaded() ) {
  showSpinner();
}

$("img.img-1").imagesLoaded()
  .done(function () {
    hideSpinner();
  });

In this case, showSpinner was never called to begin with if the image was loaded, so no flicker occurs. The other solution would be for the .done() callback to be executed immediately (without the use of async events) if the image is fully loaded so that the thread isn't handed back for rendering (thus, rendering changes from showSpinner).

That solution would read nicer, but seems like it could be hackier...so the first solution (exposing a cross-browser syncronous boolean check) might be best.

Thanks!
~ Jonathan

@desandro
Copy link
Owner

Sorry, but I will not be able to resolve this issue.

@rhys-vdw
Copy link

I will not be able to resolve this issue.

@desandro This seems like a useful feature. I use imagesLoaded to toggle the class on an image that has loaded - allowing me to fade it in. If the image is already cached then it creates a very distracting effect where everything in the page will fade in after the page loads.

Just wondering what your reasoning was? (If you remember)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants