Load Image and Fade In, but in sequential way - javascript

I'm trying to load my images and fade in. Its working. But lets suppose that I have 4 images. Right now, my script its working by loading the last image, not the first. How can I make my js load the first image, and just start loading the second after the first has been loaded?
Here's my code:
$(function(){
$("a").click(function(){
$("#load").load('load.html', function() {
$('#load img').hide();
alert($("#load img").length);
$('#load img').each( function(){
$(this).on('load', function () {
$(this).fadeIn();
});
});
});
return false;
});
});

See http://jsfiddle.net/5uNGR/15/
Try something where you are not trying to perform a fadeIn on each image as they load, but test the ok-ness of the next image in your animation queue each time ANY load event happens, then on the animation callback, see if the next one is ready. Here is a script that should work.
BTW, see http://www.sajithmr.me/javascript-check-an-image-is-loaded-or-not for more on image readiness testing.
$(function () {
// util fn to test if image loaded properly
var isImgLoadOk = function (img) {
if (!img.complete) { return false; }
if (typeof img.naturalWidth != "undefined" && img.naturalWidth == 0) {
return false;
}
return true;
};
$("a").on('click', function () {
$("#load").load('load.html', function () {
var imgs = $('#load img').hide(), //create image array and hide (chaining)
animIndex = 0, //position in the animation queue
isFading = false; //track state of whether an animation is in prog
// this is a load handler AND is called in the fadeIn callback if
// not at last image in the collection
var fadeNextImg = function () {
// make sure a load event didn't happen in the middle of an animation
if (isFading) return;
// last image in animation queue?
var isLast = animIndex == imgs.length - 1;
// get the raw image out of the collection and test if it is loaded happily
var targetImage = imgs[animIndex];
if (isImgLoadOk(targetImage)) {
// jQuery-up the htmlImage
targetImage = $(targetImage);
// increment the queue
animIndex++;
// set animation state - this will ignore load events
isFading = true;
// fade in the img
targetImage.fadeIn('slow', function () {
isFading = false;
// test to see if next image is ready to load by
// recursively calling the parent fn
if (!isLast) fadeNextImg();
});
}
};
imgs.on('load', fadeNextImg);
});
return false;
});
});

Ron's solution is a little over-engineered IMO. If your intention is indeed to load all of the images before the animation starts, then you could do something similar to the following:
$(function(){
$("a").click(function(){
$("#load").load('load.html', function() {
$('#load img').hide(); // I would recommend using css to hide the image instead
alert($("#load img").length);
$("#load img").each(function(i, image) {
setTimeout(function() { // For each image, set increasingly large timeout before fadeIn
$(this).fadeIn();
}, 2000 * i);
});
});
return false;
});
});

Related

JQuery: Onload event on image not working

I am trying to call a function after the image loads completely in DOM.
The image structure is created dynamically on AJAX call success and the image url is also added in success using the result of API call.
Problem:
I want to call a function after the image loads completely in DOM.
To do this I have used JQuery load event.
Function which is called on load.
function carouselHeight() {
$('.home-banner-img-container').each(function() {
var $this = $(this);
var dynamicheight = $(this).parent();
var sectionInnerHeight = $this.innerHeight();
dynamicheight.css({
'height': sectionInnerHeight
});
});
}
I have tried below steps but it didn't worked
$(window).on('load', function() {
carouselHeight();
});
$(window).on('load', 'img.image-preview', function() {
carouselHeight();
});
$(document).on('load', 'img.image-preview', function() {
carouselHeight();
});
The first method $(window).on('load', function() {}) works perfectly on hard reload but on normal reload it is not able to find $('.home-banner-img-container') element which is inside of carouselHeight function.
Please help me to find a solution for this. Thank you.
I have found the solution on stack overflow where I have added the below code in ajax call complete method.
function imageLoaded() {
// function to invoke for loaded image
// decrement the counter
counter--;
if( counter === 0 ) {
// counter is 0 which means the last
// one loaded, so do something else
}
}
var images = $('img');
var counter = images.length; // initialize the counter
images.each(function() {
if( this.complete ) {
imageLoaded.call( this );
} else {
$(this).one('load', imageLoaded);
}
});

Animation glitches when function is triggered again before slideUp animation ends

I use the following script (along with external animate.css) which i call when I want to show a specific notification. The idea is simple; when triggered, animate - (slide in down) the notification box, along with changed notification message. When time is out, animate again (slide out up). Everything works fine, except for when i re-trigger notification function right at the time the previous call is animating out (between the timeout and start of slide up animation - see note in code).
// notification
var timer = '';
var notif = $('#notif');
var notif_txt = $('#notif #notif_txt');
var notif_orig = '#notif';
function err_notif(text = 'Prišlo je do napake!') {
clearTimeout(timer);
notif[0].style.display = 'none';
notif_txt.text(text);
notif[0].style.display = 'inline-block';
anim(notif_orig, 'slideInDown', function() {
timer = setTimeout(function(){
// if user re-triggers the notif() function in time between mark 1 and 2, it glitches out the notification system
// mark 1
anim(notif_orig, 'slideOutUp', function(){
// mark 2
notif[0].style.display = 'none';
});
}, 1500);
});
}
Other code resources:
Animate.css for css animations
https://raw.githubusercontent.com/daneden/animate.css/master/animate.css
anim() function (from animate.css's github page)
function anim(element, animationName, callback) {
const node = document.querySelector(element)
node.classList.add('animated', animationName)
function handleAnimationEnd() {
node.classList.remove('animated', animationName)
node.removeEventListener('animationend', handleAnimationEnd)
if (typeof callback === 'function') callback()
}
node.addEventListener('animationend', handleAnimationEnd)
}
If you want to prevent a concurring animation, you can check if the element already has the animated class.
if(document.querySelector(notif_orig).classList.contains("animated")){
console.log("Concurrent animation prevented.")
}else{
anim(notif_orig, 'slideInDown', function() {
//...
}

Preload all sound and images before starting animation

I'm building a simple animation web app that involves sound and images. I want it so that when a user enters the site they see a "now loading" page, and when all the images and audio files are done loading it calls a function that starts the animation. So far the code I have is roughly this:
var img1, img2;
var sound1, sound2;
function loadImages() {
img1=new Image();
img1.src="...";
img2=new Image();
img2.src="...";
img1.onload=img2.onload=handleImageLoad;
}
function loadSound() {
createjs.Sound.registerSound({id:"sound1", src:"sound1.wav"});
createjs.Sound.registerSound({id:"sound2", src:"sound2.wav"});
createjs.Sound.addEventListener("fileload", handleSoundLoad);
}
function handleImageLoad(e) {
//Do something when an image loads
}
function handleSoundLoad(e) {
//Do something when a sound loads
if(e.id=="sound1") sound1 = createjs.Sound.createInstance("sound1");
else if(e.id=="sound2") sound2 = createjs.Sound.createInstance("sound2");
}
$(document).ready(function() {
//overlay a "now loading" .gif on my canvas
...
...
loadSound();
loadImages();
}
// call this when everything loads
function start() {
//remove "now loading..." overlay .gif
...
...
//start animating
}
handleImageLoad() and handleSoundLoad() are invoked independently of each other so I can't rely on them on calling start(). How can I figure out when everything is loaded? What callback function(s) can I use to achieve this?
Using the built-in SoundJS registerSound method is not bad, but PreloadJS will handle both Sounds and images (and other types) in a single queue. Check out the examples in the PreloadJS GitHub.
http://preloadjs.com and
http://github.com/CreateJS/PreloadJS/
This is probably not the best solution, but I did something similar this way:
var lSnd = false;
var lImg = false;
$(document).ready(function(){
setInterval(checkLoadComplete,1000);
});
function loadSound(){
//loadingSound
//on load complete call= soundLoadingComplite();
}
function soundLoadingComplite(){
//do some stuff
lSnd = true;
}
function loadImages(){
//loadingImages
//on load complete call= imageLoadingComplite();
}
function imageLoadingComplite(){
//do some stuff
lSnd = true;
}
function checkLoadComplete(){
if(lSnd&&lImg){
startAnimation();
//clear interval
}
}
Hope this helps.
I'd be doing it this way:
function loadSound(){
songOK = false;
song = new Audio()
song.src = uri;
song.addEventListener('canplaythrough', function(){ songOK = true; }, false)
return songOK;
}
function loadImage(){
pictOK = false;
pict = new Image();
pict.src = uri;
pict.onload = function (){
pictOK = true;
}
return pictOK;
}
function loadMedia(){
startNowLoading();
if( loadSound() && loadImage())
stopNowLoading();
else
kaboom(); //something went wrong!
}
$(document).ready(function(){
loadMedia();
}
This should allow you to execute the functions in sequence.

Using setTimeout to display one image at a time

I'm using a hover function with a fade in and fade out to show and hide images. The problem is I want each image to finish fading before the other begins to fade in.
This is what I'm trying. The setTimeout function has broke the hover function and all images are displaying when the page loads.
$(document).ready(function() {
var delay = 0;
//Everything below repeats for each image
$("#image_e_natural_minor").hide();
$("#hover_e_natural_minor").hover(
if (delay == 1) {
setTimeout(function() {
function () {
$("#image_e_natural_minor").fadeIn(1000);
}, //mouse over
function () {
$("#image_e_natural_minor").fadeOut(1000);
delay = 0;
} //mouse out
); //hover close
},1000); // delay time
}
else {
$("#hover_e_natural_minor").hover(
function () {
delay = 1;
$("#image_e_natural_minor").fadeIn(1000);
}, //mouse over
function () {
$("#image_e_natural_minor").fadeOut(1000);
delay = 0;
} //mouse out
); //hover close
}
This is what I had before that works but it will display two images at once.
$("#image_e_natural_minor").hide();
$("#hover_e_natural_minor").hover(
function () {
$("#image_e_natural_minor").fadeIn(1000);
}, //mouse over
function () {
$("#image_e_natural_minor").fadeOut(1000);
} //mouse out
); //hover close
$("#image_e_harmonic_minor").hide();
$("#hover_e_harmonic_minor").hover(
function () {
$("#image_e_harmonic_minor").fadeIn(1000);
}, //mouse over
function () {
$("#image_e_harmonic_minor").fadeOut(1000);
} //mouse out
); //hover close
Sorry for the poor syntax. I'm very new to programming.
jQuery functions fadeIn and fadeOut both have a callback param which is triggered when the animation finishes, so you can hook the fadeIn for current image call right when fadeOut finishes.
But: try this on a single image first; once you have it working try to rewrite it in a function you can call on every image. Remember DRY principle: Don't Repeat Yourself.
EDIT:
What I mean is: When hover over image A 'hover detector', the function should first fadeOut the currently visible image B (which you can get using :visible's jQuery selector) and when the fadeOut animation finishes it will call the fadeIn of image A (which you provided throw the callback param):
$("#image_e_natural_minor").hide();
$("#hover_e_natural_minor").hover(
function () {
$(".myImageClass:visible").fadeOut(1000, function(){$("#image_e_natural_minor").fadeIn(1000)});
}, //mouse over
function () {
$("#image_e_natural_minor").fadeOut(1000);
} //mouse out
); //hover close
Again: try this with a single image, and then rewrite it so it looks like:
$("#image_e_natural_minor").hide();
$("#hover_e_natural_minor").hover(
function(){showThis('#image_e_natural_minor')}, //mouse over
function(){hideThis('#image_e_natural_minor')} //mouse out
); //hover close
I think what you need is something like this. (In this example you also need to set the hover images to have class='hoverI'.)
var delayF = false,
mouseOn = null;
function setHandlers() {
$(".hoverI").hover(function() {
mouseOn = $('#' + event.target.id.replace('hover_e', 'image_e'));
if (!delayF) {
mouseOn.fadeIn(1000);
mouseOn = null;
}
}, function() {
var image = $('#' + event.target.id.replace('hover_e', 'image_e'));
if (mouseOn == image) mouseOn = null;
delayF = true;
image.fadeOut(1000, function() {
delayF = false;
if (mouseOn) {
mouseOn.fadeIn(1000);
mouseOn = null;
}
});
});
}
$("#image_e_natural_minor").hide();
$("#image_e_harmonic_minor").hide();
setHandlers();​

does jQuery stop() work on custom functions?

There are three images that I have made a tooltip for each.
I wanted to show tooltips within timed intervals say for 2 seconds first tooltip shows and for the second interval the 2nd tooltips fades in and so on.
for example it can be done with this function
function cycle(id) {
var nextId = (id == "block1") ? "block2": "block1";
$("#" + id)
.delay(shortIntervalTime)
.fadeIn(500)
.delay(longIntervalTime)
.fadeOut(500, function() {cycle(nextId)});
}
now what i want is to stop the cycle function when moseover action occurs on each of the images and show the corresponding tooltip. And again when the mouse went away again the cycle function fires.
If I understand everthing correctly, than try this code. Tt stops the proccess if you hover the image and continues if you leave the image. The stop() function will work on custom functions if you implement them like the fadeOut(), slideIn(), ... functions of jquery.
$('#' + id)
.fadeIn(500, function () {
var img = $(this).find('img'),
self = $(this),
fadeOut = true;
img.hover(function () {
fadeOut = false;
},
function () {
window.setTimeout(function () {
self.fadeOut(500);
}, 2000);
}
);
window.setTimeout(function () {
if (fadeOut === false) {
return;
}
self.fadeOut(500);
}, 2000);
});​

Categories