jQuery called with setInterval isn't animating on first interval - javascript

I have two images stacked. With setInterval(), the top one fades away, exposing the second. Then the top image switches to the bottom's src while invisible, and becomes opaque again. The second image changes to the next image and waits for the setInterval() to fade the top image and do it all over again.
It all works great, except the first time around; There's no fade. What am I not seeing?
This happens on all firefox and chrome and I assume all others.
HTML
<script type="text/javascript">
setInterval('swapImage()', 5000);
var galleryCount = 3;
</script>
...
<img id="image" src="images/gallery/01.jpg" />
<img id="imagenext" src="images/gallery/02.jpg" />
Javascript
function swapImage(imageToFadeID)
{
$("#image").animate
(
{ "opacity": "0" },
"slow",
"linear",
changeImage()
);
};
var i = 1;
function changeImage()
//counter +1
{
i = i + 1;
//add "0" to image number "j" if less than 10.
if (i < 10)
{
var j = "0" + i;
}
else
{
j = i;
}
//change top image to match bottom
var topImage = document.getElementById("imagenext").src;
document.getElementById("image").src = topImage;
//make top image reappear
document.getElementById("image").style.opacity = '1';
//change out bottom image to next
var btmImage = "images/gallery/" + j + ".jpg";
document.getElementById("imagenext").src = btmImage;
//reset counter if at end
if (i > galleryCount - 1)
{
i = 0;
}
}

I looks like you're invoking changeImage instead of passing it as a callback to animate:
Wrong:
function swapImage(imageToFadeID)
{
$("#image").animate
(
{ "opacity": "0" },
"slow",
"linear",
changeImage() // <--- !!! Remove the parentheses from this line!
);
};
Right:
function swapImage(imageToFadeID)
{
$("#image").animate
(
{ "opacity": "0" },
"slow",
"linear",
changeImage
);
};

Related

Animate background images within one data attribute

I try to create a nice animation between these background images urls, which are live in one data attribute (first image loads immediately, after 5 second the next images, after the next etc. After last one it starts from the beginning).
<div data-images="/media/jtjglhbb/main-bg-01.jpg,/media/u2bitolk/main-bg-02.jpg,/media/iasbuo5n/main-bg-04.jpg,/media/f00jm2va/main-bg-03.jpg,"></div>
var $dataImages = $('[data-images]');
var imagesList = $dataImages.data('images').split(',');
$.each(imagesList, function (index, value) {
setTimeout(function () {
$dataImages.stop().animate({ opacity: 0 }, 1000, function () {
$(this).css({ 'background-image': 'url(' + imagesList[index] + ')' })
.animate({ opacity: 1 }, { duration: 1000 });
});
}, 5000);
});
But it doesn't set up the first image, it only starts after 5 second and it runs altogether not one by one with 5 sec delay.
Obviously the logic is wrong, some help would be great.
Try like below. It should work.
image count will required to get mode value to start from beginning again.
index will hold index of image to show in background
changeImage function will be called recursively from inside so it will continuously update background.
use index = (index + 1) % imageCount; so index will start from 0 again from last index.
var $dataImages = $('[data-images]');
var imagesList = $dataImages.data('images').split(',');
// image count will required to get mode value to start from beginning again.
var imageCount = imagesList.length - 1;
// index of image to show in background
var index = 0;
// function will be called recursively from inside so it will continuously update background.
function changeImage() {
$dataImages.stop().animate({
opacity: 0
}, 1000, function() {
$(this).css({
'background-image': 'url(' + imagesList[index] + ')'
})
.animate({
opacity: 1
}, {
duration: 1000
});
});
// update index to next image url
index = (index + 1) % imageCount;
// declare timeout to call function after required time
setTimeout(changeImage, 5000);
}
changeImage();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<div style="height: 150px;" data-images="https://www.w3schools.com/howto/img_nature_wide.jpg,https://www.w3schools.com/howto/img_snow_wide.jpg,https://www.w3schools.com/howto/img_lights_wide.jpg,https://www.w3schools.com/howto/img_mountains_wide.jpg"></div>

Javascript array is not recognizing called variable

function slideShow() {
var pageSplash = document.getElementById('splash');
var image = ["pic1.jpg", "pic2.jpg", "pic3.jpg", "pic4.jpg"];
var i = 0;
while (i <= image.length) {
if (i > image.length) {
i = 0;
}
i += 1;
pageSplash.innerHTML = '<img id ="splashImage" src="file:///C:/JonTFS/JonGrochCoding/Javascript%20Practical%20Test/' + image[i] + '">';
setTimeout('slideShow', 5000);
}
}
I'm unsure why my i variable is not being recognized as the i variable from the rest of the function, so when ever I try to run my while loop it get's an error message saying that it's undefined.
I think you want setInterval instead of setTimeout, and you want you be careful that you increment i after you you update innerHTML.
function slideShow() {
var pageSplash = document.getElementById('splash');
var image = ["pic1.jpg", "pic2.jpg", "pic3.jpg", "pic4.jpg"];
var i = 0;
setInterval(function () {
if (i === image.length) {
i = 0;
}
pageSplash.innerHTML = '<img id ="splashImage" src="file:///C:/JonTFS/JonGrochCoding/Javascript%20Practical%20Test/' + image[i] + '">';
i++;
}, 5000)
}
slideShow();
You don't need a while loop. You don't need to reset i. You don't need to set innerHTML.
Click Run code snippet... to see how this works. More explanation below the code
function slideShow(elem, images, delay, i) {
elem.src = images[i % images.length];
setTimeout(function() {
slideShow(elem, images, delay, i+1);
}, delay);
}
// setup slideshow 1
slideShow(
document.querySelector('#slideshow1 img'), // target element
[ // array of images
'http://lorempixel.com/100/100/animals/1/',
'http://lorempixel.com/100/100/animals/2/',
'http://lorempixel.com/100/100/animals/3/',
'http://lorempixel.com/100/100/animals/4/',
'http://lorempixel.com/100/100/animals/5/',
'http://lorempixel.com/100/100/animals/6/'
],
1000, // 1000 ms delay (1 second)
1 // start on slide index 1
);
// setup slideshow 2
slideShow(
document.querySelector('#slideshow2 img'), // target element
[ // array of images
'http://lorempixel.com/100/100/nature/1/',
'http://lorempixel.com/100/100/nature/2/',
'http://lorempixel.com/100/100/nature/3/',
'http://lorempixel.com/100/100/nature/4/',
'http://lorempixel.com/100/100/nature/5/',
'http://lorempixel.com/100/100/nature/6/'
],
500, // 500 ms delay
1 // start on slide 1
);
#slideshow1, #slideshow2 {
width: 150px;
display: inline-block;
}
<div id="slideshow1">
<h2>Animals</h2>
<p>(1000 ms delay)</p>
<!-- initial image -->
<img src="http://lorempixel.com/100/100/animals/1/">
</div>
<div id="slideshow2">
<h2>Nature</h2>
<p>(500 ms delay)</p>
<!-- initial image -->
<img src="http://lorempixel.com/100/100/sports/1/">
</div>
This is a huge improvement because your slideshow function is reusable. It means you can use the same function for any slideshow you want. You can even run multiple slideshows on the same page, as I have demonstrated here.
As others have pointed out, the while loop is unnecessary and, as I pointed out, the setTimout was incorrectly written. The following simplifies your code significantly:
var i = 0;
function slideShow() {
var pageSplash = document.getElementById('splash');
var imageArray = ["pic1.jpg", "pic2.jpg", "pic3.jpg", "pic4.jpg"];
if(i < imageArray.length) {
pageSplash.innerHTML = '<img title='+ imageArray[i] + ' id ="splashImage" src="file:///C:/JonTFS/JonGrochCoding/Javascript%20Practical%20Test/' + imageArray[i] + '">';
}
i++;
}
setInterval(slideShow, 2000);
See: https://jsfiddle.net/dauvc4j6/8/ for a working version.
setTimeout calls the function again so you're re-initializing i to 0 every time you call it. Since you can use setTimeout to call the function recursively you don't need the while loop. Pull i out of the function altogether and make it a global variable.
//i should be global
var i = 0;
function slideShow() {
var pageSplash = document.getElementById('splash');
var image = ["pic1.jpg", "pic2.jpg", "pic3.jpg", "pic4.jpg"];
if (i >= image.length) {
i = 0;
}
i += 1;
pageSplash.innerHTML = '<img id ="splashImage" src="file:///C:/JonTFS/JonGrochCoding/Javascript%20Practical%20Test/' + image[i] + '">';
//set timeout is going to call slideShow again so if it's in the function it will call recursively, if you wanted to stop after a certain point you could nest setTimeout in an if
setTimeout(slideShow, 5000);
}
//you need to initially call the function
slideShow();

JQuery: How to change image after time with fadeIn?

I want to change an image automatically after 2000ms. The image should fade in.
My HTML:
<div class="nile-slider large-12 column">
<img alt="landing page 3" src="assets/Startseite/Slider/Slider_2.jpg">
</div>
My JS:
// change header image after 2 seconds
var images = ['Slider_1.jpg','Slider_2.jpg','Slider_3.jpg', 'Slider_4.jpg'],
index = 0, // starting index
maxImages = images.length - 1;
var timer = setInterval(function() {
var currentImage = images[index];
index = (index == maxImages) ? 0 : ++index;
$('.nile-slider img').attr('src','assets/Startseite/Slider/'+currentImage).fadeIn('slow');
}, 2000);
With this code the images changes but it does not fade in. How can I force the images to fade in (and even fade out)?
You can combine fadeOut and fadeIn() using fadeOut callback function, to achieve this.
// change header image after 2 seconds
var images = ['Slider_1.jpg','Slider_2.jpg','Slider_3.jpg', 'Slider_4.jpg'],
index = 0, // starting index
maxImages = images.length - 1;
var timer = setInterval(function() {
var currentImage = images[index];
index = (index == maxImages) ? 0 : ++index;
$('.nile-slider img').fadeOut(200, function() {
$('.nile-slider img').attr("src", 'assets/Startseite/Slider/'+currentImage);
$('.nile-slider img').fadeIn(200);
});
}, 2000);
Providing the new source as callback of fadeOut may do the trick:
$('.nile-slider img')
.fadeOut('fast',
function () {
$('.nile-slider img')
.attr('src','assets/Startseite/Slider/'+currentImage)
.fadeIn('slow');
}
);

How to get around javascript timeout of 0

Here is a fiddle: http://jsfiddle.net/hB7gY/16/
I have the following code which controls a slideshow with four quadrants. The idea is to rotate through the slideshow and dynamically change the slides based upon a predefined time frame. For instance, many times a slide has a value of 0, which means instantly load the next slide in the series.
The problem is that when using fadeIn() or animate(), they take longer than the timeout of 0. I've tried incrementing my counters when this happens, but that doesn't work.
EDIT: I think I may not have been clear in my question, but the goal is to be able to load the next image instantly, but still maintain the animation effect on the previous image, so essentially it will appear as if both images are animating simultaneously.
var slide_array = <?php echo json_encode( $slides ); ?>;
jQuery(document).ready(function(){
var c =0;
var slide = 0;
var counter = 1000;
for (var i=0;i<slide_array.length;i++){
jQuery('#slide_'+i).attr('src', slide_array[i]["url"]);
}
var intFn = function(){
clearTimeout(interval);
c++;
slide++;
if (slide == slide_array.length) { slide = 0; }
if (c == 4){ c = 0; }
jQuery('#slide_'+c).attr('src',slide_array[slide]['url']).animate({
opacity: 0.5
}, 100, function() {
jQuery('#slide_'+c).attr('src',slide_array[slide]['url']).animate({
opacity: 1
}, 100);
});
counter = slide_array[slide]['duration'] * 1000;
//if (counter < 1000 ) { counter = 400; }
interval = setTimeout(intFn, counter);
}
var interval = setTimeout(intFn, 2500);
});

Restart / Refresh Javascript Function or Timer

I have the following code on my website....
At the moment, when "Test 1" is clicked the animation starts. After that, when "Test 2" or "Test 3" is clicked the animation does not restart...
How would I restart the animation when any of the links are clicked ?
And is it possible to have a Fade out and Fade In, after a link has been clicked ?
HTML Markup:
<div id="anim"></div>
</br>
</br>
<li id="item1"><span></span>Test 1</li>
<li id="item2"><span></span>Test 2</li>
<li id="item3"><span></span>Test 3</li>
CSS:
#anim {
width: 14px; height: 14px;
background-image: url(http://mail.google.com/mail/im/emotisprites/wink2.png);
background-repeat: no-repeat;
}
Javascript:
var scrollUp = (function () {
var timerId, height, times ,i = 0 , element;
return {
stop : function(){
clearInterval( timerId );
},
init :function( h, t, el ){
height = h;
times = t;
element =el ;
},
start : function ( ) {
timerId = setInterval(function () {
if (i > times) // if the last frame is reached, set counter to zero
clearInterval(timerId);
element.style.backgroundPosition = "0px -" + i * height + 'px'; //scroll up
i++;
}, 100); // every 100 milliseconds
}
};
})();
scrollUp.init(14, 40, document.getElementById('anim'));
// start animation:
document.getElementById('item1').addEventListener('click', function(){
scrollUp.start();
}, false );
Here's a Fiddle : http://jsfiddle.net/ctF4t/3/
As far as I understand, you want the animation (whatever state it is currently) to restart if one of the buttons is clicked?
Well, if so, first you should call the stop function everytime before the start:
document.getElementById('item1').addEventListener('click', function(){
scrollUp.stop();
scrollUp.start();
}, false );
Additionally, the index has to be reset in the stop:
stop : function(){
clearInterval( timerId );
i = 0;
},
This will do the job for the button #item1. Here is a demo. Applying this to the others should not be the big trouble now. For example bind the event to the <body/> and read the target:
function startAnimation(e) {
e = e || window.event;
var target = e.target || e.srcElement;
target = target.parentNode;
if (!target.id.match(/item[0-3]/)) {
return e;
}
scrollUp.stop();
scrollUp.start();
}
document.body.addEventListener('click',startAnimation,false);
Here is the complete demo.
How would I restart the animation when any of the links are clicked ?
To define a restart, you'll want to stop any still-running intervals, reset i to 0 since that marks the "beginning," and start a new interval:
return {
// ...
restart: function () {
this.stop();
i = 0;
this.start();
}
};
You then need to bind to each li so they can all perform a restart():
var items = document.querySelectorAll('#item1, #item2, #item3');
for (var i = 0, l = items.length; i < l; i++) {
items[i].addEventListener('click', function () {
scrollUp.restart();
}, false);
}
I changed your fiddle to this: http://jsfiddle.net/M5pe8/1/
It seems you didn't reset the "i" var, so the animation couldn't restart from the beginning (i.e., from "zero"); i left the alert line (but is commented out), to show you how i got to my conclusions:
if (i > times) // if the last frame is reached, set counter to zero
{
//alert(i + ' > ' + times);
clearInterval(timerId);
i = 0;
}
else
{
element.style.backgroundPosition = "0px -" + i * height + 'px'; //scroll up
i++;
}
And, of course, i added the lines to bind the click event that starts the animation to the other two links (just for completeness). Now, clicking the second time the animation restarts. Is that what you needed?
EDIT: Link to fiddle corrected

Categories

Resources