setInterval running really slow - javascript

I made a website where I need to animate strings that are longer than the containing parent.
This is the website: Here
If you click on next, you can see multiple pages of breeders with long names, that need to animate from left to right, but this only happens after 10 or 15 seconds and it takes a long time for it to start.
Now I have checked my code and this is where I create my functions:
function newsTicker() {
console.log('newsTicker')
verifyLength();
$('.breeder').not('.short-breed-name').each(function() {
var breederNameWidth = $(this).find('.breeder_name').width();
var divBreederNameWidth = $(this).find('.breeder_name_div').width();
var diff = Math.max(parseInt(breederNameWidth - divBreederNameWidth),0);
// console.log('diff:',diff)
$(this).find('.breeder_name').animate({
marginLeft: -diff
}, 3000,
function(){
$(this).animate({
marginLeft : 0
},3000)
})
})
}
function verifyLength() {
// console.log('verifyLength')
$('.breeder.visible').each(function() {
// debugger
var breederNameWidth = $(this).find('.breeder_name').width() + 10;
var divBreederNameWidth = $(this).find('.breeder_name_div').innerWidth();
if(breederNameWidth < divBreederNameWidth) {
$(this).addClass('short-breed-name');
$(this).find('.breeder_name').css({'width':'100%','text-align':'center'})
}
})
}
And this is where I call newsTicker:
function breederAnimate(){
verifyLength();
newsTicker();
setInterval(newsTicker, 1000);
}
Why is it so slow when my times are between 1 and 3 seconds?

You should be calling setTimeout not setInterval because you only want your animation to run once. You're restarting your animations every second
Also, you should be cancelling existing setIntervals when you click next or previous

Related

How to animate blocks one after the other?

With this bit of JavaScript I hoped to animate some block element one after the other by adding CSS animation classes with a time out of 500 milliseconds.
Unfortunately it waits one time and all the boxes slide up at once after the one wait.
Here is the script so far:
var blocks = $('.block');
blocks.each(function(index, obj) {
var block = $(obj);
setTimeout(function() {
block.addClass('animated slideInUp');
}, 500);
});
So, how do I add these classes asynchronically so the boxes on the page will slide up one after the other?
You can consider the index of the each() loop so that in setTimeout() the time will be multiple of 500. With this the boxes will appear in each 500 milliseconds as the setTimeout() will have timeout time as 500, 1000, 1500, ... and so on.
var blocks = $('.block');
blocks.each(function(index, obj) {
var block = $(obj);
setTimeout(function() {
block.addClass('animated slideInUp');
}, 500*index);
});

Do not shoot new animation until the current does not end

I have the following animation to a leaping animation
$("#bounce").click(function() {
doBounce($(this), 3, '10px', 300);
});
function doBounce(element, times, distance, speed) {
for(i = 0; i < times; i++) {
element
.animate({marginTop: '-='+distance},speed)
.animate({marginTop: '+='+distance},speed);
}
}
But, when I click several times on the element, various animation starts, thus forming a stack of events. I would like to click and while the current animation does not end, not be possible to launch other shots, even if I click on the element. How to do this?
One solution is to use the :animated selector:
function doBounce(element, times, distance, speed) {
if (element.is(":not(:animated)")) {
for(i = 0; i < times; i++) {
element
.animate({marginTop: '-='+distance},speed)
.animate({marginTop: '+='+distance},speed);
}
}
}
There a several ways, but I would suggest you use Javascript scope to set a bool that returns back to true if the animations are finished. See this Fiddle and hit test a few times when it's animating.
(function () {
var animate = true;
$("#bounce").click(function () {
// Only fire when true, which it is by default.
if (animate) {
doBounce($(this), 3, '10px', 300);
}
});
function doBounce(element, times, distance, speed) {
// Set to false to prevent new calls.
animate = false;
for (i = 0; i < times; i++) {
element.animate({
marginTop: '-=' + distance
}, speed)
.animate({
marginTop: '+=' + distance
}, speed);
}
// Set the var back to true after animations are finished.
// https://api.jquery.com/promise/
element.promise().done(function () {
animate = true;
alert(animate);
});
}
})();
One other solution is a throttle function. A throttle function wraps another (child) function and prevents calls to the child from happening more than once every n milliseconds. Here's an example using the fantastic lodash library:
var doBounce = _.throttle(function(element, times, distance, speed) {
// here, put your original doBounce code
}, lengthOfAnimation);
Now, no matter how many times you call doBounce(/* some arguments */);, the actual code won't run more than once every lengthOfAnimation milliseconds.
Of course, this will only work if the animation is the same length every time.
lodash: https://lodash.com/
throttle: https://lodash.com/docs#throttle

Simple loop for images

I'm trying to build a simple image slider (but using a fade effect). Every two seconds, the image should change to another image. At the end, it should call repeat_sponsor() again, to start over, so it becomes a loop.
I've written this (highly ineffective) code for 5 images. Turns out I'm going to need it for around 50 images. My editor just freezes when I add too much code.
I've tried using while-loops, but I just can't figure it out how to do this the right way.
Anyone who can help me with this?
function repeat_sponsor()
{
$("#sponsor2").hide();
$("#sponsor3").hide();
$("#sponsor4").hide();
$("#sponsor5").fadeOut("slow");
$("#sponsor1").fadeIn("slow", function() {
setTimeout(function(){$("#sponsor2").fadeIn("slow", function() {
setTimeout(function(){$("#sponsor3").fadeIn("slow", function() {
setTimeout(function(){$("#sponsor4").fadeIn("slow", function() {
setTimeout(function(){$("#sponsor5").fadeIn("slow", ...
(function (){
var cnt = 50; //set to the last one...
var max=50;
function show() {
$("#sponsor" + cnt).fadeOut("slow"); //if you want the fadeout to be done before showing next, put the following code in the complete callback
cnt++;
if(cnt>max) {
cnt=1;
}
$("#sponsor" + cnt).fadeIn("slow");
window.setTimeout(show, 2000);
}
show();
})();
But the real issue is the fact you are loading tons of images from the start. You will be better off changing it so you only have a small subset of images and change the source.
You should use some sort of for loop and a class for hiding the images. and add a max value that if checks out resets c & i
var i=0;
var c=1;
function repeat_sponsor()
{
$("#sponsor"+i).fadeOut("slow");
$(".sponsers").hide()
$("#sponsor"+c).fadeIn("slow", function() {
window.setTimeout(repeat_sponsor(), 3000);
}
i++;
c++;
}
Just run a function every two seconds with setInterval and appropriately target your different sponsor divs:
var i = 1;
var max = 50;
setInterval(function() {
// Could target all other sponsor images with a class "sponsor"
$('.sponsor').fadeOut();
// Execute code on the target
$("#sponsor" + i).fadeIn();
if (i === max) {
i = 0;
}
i++;
}, 2000);

javascript thread

http://jsfiddle.net/andersb79/SNTb3/1/
In this example when you click run. The div is animated in after it got its 1000 hellos.
If i comment the for loop in the beginning out and comment in the other for loop the animation starts before the append is running.
But then the animation is not running smooth. Can you in some way make this happend or is it impossible in javascript.
I want it to load up the divDocument in the meantime it is animated in. I dont mean it should be live adding but I dont want it to mess upp the animation and I dont want to loose time by adding the 1000 records before the animation is started.
Hope that you understand my qustion.
If you're going to add 10000 elements in one go it will block any other activity until it has finished.
If you start the animation and then do the add, it's jerky because for a short while the system is busy adding the divs, and then suddenly it realises that it's running behind on the animation and it has to rush to catch up. Note that the animation does not get interleaved with the addition of the elements.
The best way to solve this is to add the elements in batches, using setTimeout to trigger the next batch each time.
The batching gives the background thread time to run any other events, such as the animation handlers.
See http://jsfiddle.net/alnitak/yETt3/ for a working demo using batching. The core of the sample is this:
var n = 0,
batch = 100;
function nextBatch() {
for (var i = 0; i < batch && n < 10000; ++i, ++n) {
$("#divDocument").append("<div>hello</div>");
}
if (n < 10000) {
setTimeout(nextBatch, 0);
}
}
setTimeout(nextBatch, 0);
which adds elements 100 at a time, with the setTimeout call allowing the event handling thread to jump in and process animations and other UI events.
For example you can use setTimeout
$(document).ready(function () {
$(".openWindow").click(function () {
setTimeout(function() {
var divToShow = $("#divDocument");
var windowWidth = $(window).width();
var leftOut = (windowWidth * -1);
var leftIn = windowWidth + 500;
divToShow.css({ left: leftIn });
divToShow.show();
divToShow.animate({ left: 0 }, 400, function () {
divToShow.addClass("visibleDiv");
});
}, 2000);
for (var i = 0; i < 10000; i++) {
$("#divDocument").append("<div>hello</div>");
}
});
});
If you want to run animation after that elements was add you must create function for append elements and in end of this function call animation. If you want run this as async you must use setTimeout(func, 0) for animation and for elements add.

Getting one slide in my slideshow to stay longer between intervals

What I'm trying to accomplish is a slideshow that has one slide that lasts 10 seconds-- while all other slides in the slideshow last 4 seconds. In my code below, the current.id==1 condition is my first slide. When the DOM loads, it checks what slide is first, and if it's current.id==1, it makes all transitions 10 seconds. Which isn't exactly what I want. Any suggestions how I could get the all other slides to interval every 4 seconds and still keep my main slide lasting 10 seconds every time it flips back to that slide?
Sorry if that is a bit confusing. Thanks for the help guys!
/* Setting auto-advance every 10 seconds for main slide, 4 seconds for all others */
var auto;
if (current.id==1) { //this is the only slide I want lasting 10 seconds.
auto=setInterval(function(){
next();
},10*1000); //10 seconds for MAIN slide
} else { // all other slides should interval every 4 seconds.
auto=setInterval(function(){
next();
},4*1000);//4 seconds each other slide.
}
I write my JS like this. It makes it far more readable in my opinion and really helps Though normally I don't include comments like this
Your next() function should call itself
$(document).ready(function () {
var Page = {};
Page.slider = (function () {
return {
init: function () {
setTimeout(function () {
Page.slider.nextSlide();
}, 10*1000);
},
nextSlide: function () {
var duration = 4;
if (Page.slider.isShowingFirst()) {
duration = 10;
}
//code to handle transitioning slides
setTimeout(function () {
Page.slider.nextSlide();
}, duration*1000);
},
isShowingFirst: function () {
//return boolean on whether it's showing the first slide or not
}
}
})();
Page.slider.init();
});
You can't use setInterval() if you want a varying interval because you only call it once and then it runs repeatedly with the same interval until you stop it. You could use setTimeout() on each slide like this:
if (current.id == 1) { //this is the only slide I want lasting 10 seconds.
setTimeout(next, 10*1000); //10 seconds for MAIN slide
} else { // all other slides should interval every 4 seconds.
setTimeout(next, 4*1000);//4 seconds each other slide.
}
P.S. You may also want to notice that you don't need an anonymous function for setTimeout() or setInterval() if all you want it to do is call a function you already have defined as in this example.
You should use setTimeout instead of setInterval.
var auto;
if (current.id==1) { //this is the only slide I want lasting 10 seconds.
auto=setTimeout(function(){
next();
},10*1000); //10 seconds for MAIN slide
} else { // all other slides should interval every 4 seconds.
auto=setTimeout(function(){
next();
},4*1000);//4 seconds each other slide.
}

Categories

Resources