Autozoom Effect - javascript

I'm trying to create an auto-zoom but I'm stuck in here.
I have this function
panZoom.zoomOut(num);
and I need to call it n times with a little delay to create a nice zoomOut effect
I'm using
for(i=0; i<10;i++){
panZoom.zoomOut(1);
};
But it executes too fast to create an animation.
I also tried setTimeout:
function myLoop () {
setTimeout(function () {
panZoom.zoomOut(1);
i++;
if (i < 10) { // if the counter < 10, call the loop function
myLoop(); // .. again which will trigger another
} // .. setTimeout()
if (i==10){
i=1;
}
}, 100);
};
But the action after the setTimeout execute without waiting for setTimeout to finish (and it's obvious I know but there is not delay function.)
How can I make a smooth zoom effect?

You probably want to do something like this:
for ( var i = 0; i < 10; i++ ) {
setTimeout(function(){
panZoom.zoomOut(1);
}, 100 * i);
}

Related

setTimeout function in JavaScript doesn't output number at correct time intervals

I'm not understanding why this function outputs 1-5 in successive order as intended, but at 1 second intervals rather than 1,2,3, etc. seconds. I'm unfamiliar with the setTimeout function and I understand that something is going on with the arguments to the function here that I'm not seeing.
var counter = function() {
for (var i = 1; i <= 5; i++) {
(function(x){
setTimeout(function timer() {
console.log(x);
}, (x * 1000));
})(i);
}
};
You can avoid the for loop by calling it recursively, just pass the start and stop index.
var counter = function (x, y) {
setTimeout(function timer() {
console.log(x);
if (x != y) counter((x + 1),y);
}, (x * 1000));
};
counter(1, 5);
Fiddle demo
Because you are immediately placing all your calls to setTimeout. So, during the same event, JS receives the instruction to call timer: after 1000ms, after 2000ms, after 3000ms, after 4000ms and after 5000ms. Which is exactly what it does, so timer is called every 1 second.
If you wish to progressively increase the interval, your loop should be rewritten as a recursive loop, in which the next call to setTimeout is performed by timer.
As #putvande said you are setting all 5 timeouts at the same time with different intervals.
var counter = function(){
for (var i=1; i<=5; i++) {
console.log('setting timer for ' + i);
(function(x){
setTimeout( function timer(){
console.log(x);
}, (x*1000) );
})(i);
}
};
counter();
An extra log statement show this. Your timers are firing at the right interval, 1st one at 1 second, 2nd one at 2 seconds, etc.

setInterval within a for-loop not working

What I want is an infinite loop that alerts 1, 2, 3, 1, 2, 3, ... with an interval of 2000 milliseconds. But it's not working. The console's not showing any error though. What's the problem here?
for (i = 1; i <= 3; i++) {
setInterval(function() {
alert(i);
}, 2000);
if (i == 3) {
i = 0;
}
}
This will do:
var i = 0;
setInterval(function () {
i += 1;
if (i == 4) {
i = 1;
}
alert(i);
}, 2000);
I've checked it chrome too.
It outputs 1,2,3,1,2,3... as you have requested.
you can not setInterval() inside a for loop because it will create multiple timer instance.
The setInterval() method calls a function or evaluates an expression at specified intervals (in milliseconds).
The setInterval() method will continue calling the function until clearInterval() is called, or the window is closed.
The ID value returned by setInterval() is used as the parameter for the clearInterval() method.
Tip: To execute a function only once, after a specified number of milliseconds, use the setTimeout() method.
var i = 0
function test() {
i = i % 3;
++i;
alert(i);
};
setInterval('test()', 2000);
You would not need a loop for this, an interval already goes on infinitley. Try this instead:
var i = 1;
setInterval(function() {
alert(i);
i++;
if(i > 3) {
i = 1;
}
}, 2000);
The reason why this is not working is because you enter the infinite loop in a blocking state, meaning that the interval is never entered as the browser is busy looping. Imagine the browser can only do one thing at a time, as in a single thread, so the loop is it, and cannot do anything else until it's done, and in your case it never is, therefore the interval is waiting for it's turn, which it never gets.
You could make it none blocking like this:
function recursion () {
for (var i = 1; i < 4; i++) {
var num = i;
setInterval(function() {
console.log(String(this));
}.bind(num), 2000);
}
recursion ();
}
recursion ();
my best suggestion is . use event monogramming righterthen loop ,
first make a function then after completing of setInterval call to next function and so on.. that's how u can solve this p

Why isn't clearInterval working in this code?

There is a function which sets an interval using setInterval(), but even after calling clearInterval(), I can see in the console that the else condition is still running. How can I clear that interval properly?
function increase(old, step, neu) {
var i = 0;
var delay2;
function countUp() {
if (i < 5) {
old += step;
// console.log("increase")
$("#total-price-value").text(old + " dollors");
$("#total-price-value").digits();
i++;
delay2 = setInterval(countUp, 80);
} else {
clearInterval(delay2);
console.log(delay2);
}
}
countUp();
}​
It looks like you're a little confused about the difference between timeouts and intervals. Timeouts fire only once; intervals fire many times. If you're using an interval, you probably only want to set it once (you're setting it every time). If you're using a timeout, you probably want to set it every time (like you're doing).
In order to fix the problem, you'll either want to switch to timeouts (probably the easiest; just a search/replace) or only set the interval once.
For example, here is how one might use setTimeout to count up to five:
var count = 0;
function timeoutFired() {
count++;
if(count < 5) {
setTimeout(timeoutFired, 1000);
}
}
setTimeout(timeoutFired, 1000);
Using timeouts, we don't need to clear to stop it from counting; simply not setting a timeout will prevent it from running again.
Here is how one might use setInterval:
var count = 0;
function intervalFired() {
count++;
if(count >= 5) {
clearInterval(interval);
}
}
var interval = setInterval(intervalFired, 1000);
If you want some code running periodically using intervals to stop, you must call clearInterval. Note that we only call setInterval once, versus setTimeout every time we didn't want it to continue.
Apparently, you have mistaken setInterval for setTimeout. setInterval runs the enclosed function every n milliseconds while setTimeout executes only once after n milliseconds.
I suppose you wanted to "tick until 5" so here's a sample:
function increase(old, step, neu) {
var i = 0;
interval = setInterval(function() {
if (i < 5) {
//do something at this "tick"
console.log(i);
i++;
} else {
//else, stop
clearInterval(interval);
}
},80);
}
increase();

Using setTimeout to update progress bar when looping over multiple variables

Suppose you have 3 arrays you want to loop over, with lengths x, y, and z, and for each loop, you want to update a progress bar. For example:
function run() {
x = 100;
y = 100;
z = 10;
count = 0;
for (i=0; i<x; i++) {
//some code
for (j=0; j<y; j++) {
// some code
for (k=0; k<z; k++) {
//some code
$("#progressbar").reportprogress(100*++count/(x*y*z));
}
}
}
}
However, in this example, the progress bar doesn't update until the function completes. Therefore, I believe I need to use setTimeout to make the progress bar update while the function runs, although I'm not sure how to do that when you have nested for loops.
Do I need to break each loop up into its own function, or can I leave them as nested for loops?
I created a jsfiddle page in case you'd like to run the current function: http://jsfiddle.net/jrenfree/6V4Xp/
Thanks!
TL;DR: Use CPS: http://jsfiddle.net/christophercurrie/DHqeR/
The problem with the code in the accepted answer (as of Jun 26 '12) is that it creates a queue of timeout events that don't fire until the triple loop has already exited. You're not actually seeing the progress bar update in real-time, but seeing a late report of what the values of the variables were at the time they were captured in the inner closure.
I'd expect that your 'recursive' solution looks a bit like using continuation-passing style to ensure that your loop doesn't continue until after you've yielded control via setTimeout. You might not know you were using CPS, but if you're using setTimeout to implement a loop, you're probably pretty close to it.
I've spelled out this approach for future reference, because it's useful to know, and the resulting demo performs better than the ones presented. With triple nested loops it looks a bit convoluted, so it may be overkill for your use case, but can be useful in other applications.
(function($){
function run() {
var x = 100,
y = 100,
z = 10,
count = 0;
/*
This helper function implements a for loop using CPS. 'c' is
the continuation that the loop runs after completion. Each
'body' function must take a continuation parameter that it
runs after doing its work; failure to run the continuation
will prevent the loop from completing.
*/
function foreach(init, max, body, c) {
doLoop(init);
function doLoop(i) {
if (i < max) {
body(function(){doLoop(i+1);});
}
else {
c();
}
}
}
/*
Note that each loop body has is own continuation parameter (named 'cx',
'cy', and 'cz', for clarity). Each loop passes the continuation of the
outer loop as the termination continuation for the inner loop.
*/
foreach(0, x, function(cx) {
foreach(0, y, function(cy) {
foreach(0, z, function(cz) {
count += 1;
$('#progressbar').reportprogress((100*(count))/(x*y*z));
if (count * 100 % (x*y*z) === 0) {
/*
This is where the magic happens. It yields
control to the javascript event loop, which calls
the "next step of the foreach" continuation after
allowing UI updates. This is only done every 100
iterations because setTimeout can actually take a lot
longer than the specified 1 ms. Tune the iterations
for your specific use case.
*/
setTimeout(cz, 1);
} else {
cz();
}
}, cy);
}, cx);
}, function () {});
}
$('#start').click(run);
})(jQuery);
You can see on jsFiddle that this version updates quite smoothly.
If you want to use setTimeout you could capture the x, y, z and count variables into a closure:
function run() {
var x = 100,
y = 100,
z = 10,
count = 0;
for (var i=0; i<x; i++) {
for (var j=0; j<y; j++) {
for (var k=0; k<z; k++) {
(function(x, y, z, count) {
window.setTimeout(function() {
$('#progressbar').reportprogress((100*count)/(x*y*z));
}, 100);
})(x, y, z, ++count);
}
}
}
}
Live demo.
Probably a jquery function in reportprogress plugin uses a setTimeout. For example if you use setTimeout and make it run after 0 milliseconds it doesn't mean that this will be run immediately. The script will be executed when no other javascript is executed.
Here you can see that i try to log count when its equal to 0. If i do it in setTimeout callback function then that is executed after all cycles and you will get 100000 no 0. This explains why progress-bar shows only 100%. js Fiddle link to this script
function run() {
x = 100;
y = 100;
z = 10;
count = 0;
for (i=0; i<x; i++) {
//some code
for (j=0; j<y; j++) {
// some code
for (k=0; k<z; k++) {
//some code
if(count===0) {
console.log('log emidiatelly ' + count);
setTimeout(function(){
console.log('log delayed ' + count);
},0);
}
count++;
}
}
}
}
console.log('started');
run();
console.log('finished');
wrapping everything after for(i) in setTimeout callback function made the progress-bar work. js Fiddle link
Edit:
Just checked that style setting code for item is actually executed all the time. I think that it might be a browser priority to execute javascript first and then display CSS changes.
I wrote a another example where i replaced first for loop with a setInterval function. It's a bit wrong to use it like this but maybe you can solve this with this hack.
var i=0;
var interval_i = setInterval(function (){
for (j=0; j<y; j++) {
for (k=0; k<z; k++) {
$("#progressbar").reportprogress(100*++count/(x*y*z));
}
}
i++;
if((i<x)===false) {
clearInterval(interval_i);
}
},0);
JS Fiddle
I've found a solution based on the last reply but changing the interval time to one. This solution show a loader while the main thread is doing an intensive task.
Define this function:
loading = function( runme ) {
$('div.loader').show();
var interval = window.setInterval( function() {
runme.call();
$('div.loader').hide();
window.clearInterval(interval);
}, 1 );
};
And call it like this:
loading( function() {
// This take long time...
data.sortColsByLabel(!data.cols.sort.asc);
data.paint(obj);
});

How to cause delay that work synchronic with the code -javascript

for(i=0;i<10;i++){
code
setTimeout
code
}
I want to prevent from the loop to proceed until timeout is finish ,any idea??
This repeats 10 times:
var j = 10;
setTimeout(someFunction, 1000);
function someFunction()
{
if (j > 0)
setTimeout(someFunction, 1000);
j = j - 1;
}
var i = 0;
nextMove( );
function nextMove( ) {
i++;
if( i != 10 ) setTimeout(nextMove,3000);
}
If you've got Function.prototype.bind() available:
function operation() {
if (!this) return;
// do something
setTimeout(operation.bind(--this), 1000);
}
setTimeout(operation.bind(10), 1000);
I believe there's no way to delay the execution of a block of code that follows an instruction that is being executed.
The only thing you can do is to wrap the code that need to be delayed around a function and use set time out just like the previous comments suggest.

Categories