recursive requestAnimationFrame() javascript loop jumps directly to the end - javascript

I'm trying to learn animating in javascript.
I have a path array with x and y coordinates that I try to move through with recursion. But instead of moving the box (box[1]) one step at a time it jumps directly to the last position. If i add an alert in the loop then the animation will "work", so that it just moves the box one step at a time between each alert.
function followPath(){
box1[1].style.left = path[index][0]+'px';
box1[1].style.top = path[index][1]+'px';
index++; //I put an alert("hi"); here and it "worked"
if(index < path.length)
requestAnimationFrame(followPath());
}
function buttonPress(){
index = 0;
followPath();
}
What causes this?
As a sidenote, I had the same sort of problem when i tried to pass variables to a similar recursive function that worked just fine before i tried to pass variables to it.
Thanks.

Argument to requestAnimationFrame is a function, not what function returns. The line:
requestAnimationFrame(followPath());
should be
requestAnimationFrame(followPath);

Related

Why cant I scroll browser window in a loop in console?

I want to scroll down the browser window in a loop in console. I want it so that every time a scroll down (x)px down I stop, do something and then scroll (x)px again and then stop etc. until the page with ends (its a very long one, I want to parse info from it).
But when I started I stumbled upon an issue, that the scrolling function is executed only once, after the loop ends.
let i = 0;
scrollDownTillEnd = () => {
for(i; i<100; i++) {
window.scrollBy(0, 1000);
};
scrollDownTillEnd();
(it is a simplified example, but the idea should be clear)
I put the code in the console, being on a page I want to scroll, and get then the value of i at the end of the loop and only one scroll down.
Please, explain me, why this piece of code behaves like this and how to make it work, as I mentioned before (in every loop it scrolls a little bit).
Thank you!
Let me help address a few issues going on here.
1) You have an infinite loop going on because you are not checking that i is less than 100 even though you are incrementing it each time. You need to check that i < 100 so that the loop will eventually end. In your loop, 0 will always be less than 100 so the loop will never end.
2) You have a syntax error in your example because you're not actually closing out the scrollDownTillEnd function with a curly brace before calling the function itself.
3) Lastly, as good practice, you need to reset your i variable to 0 each time so that we can run this piece of code over and over again. The way you have it set up in your example, since i will be equal to 100 at the end of the first run, the loop won't ever run again after that until you reset i to 0 again. The easiest way to do this is to just initialize i to a value of 0 each time you execute this loop.
Try something like this:
scrollDownTillEnd = () => {
for(let i = 0; i < 100; i++) {
window.scrollBy(0, 1000);
};
};
scrollDownTillEnd();
You can use setInterval() since for loop will executes only once
function scrollDownTillEnd(countryDropdownList)
{
let scrollingInterval = setInterval(function(){
window.scrollBy(0,1000)
// write your condition
if (window.scrollHeight > 10000)
{
clearInterval(scrollingInterval)
}
},100)
}
scrollDownTillEnd();

Javascript Timeout between for loop?

So it's probably some mis-understanding on the best way to use the setTimeout method provided by javascript but im having trouble implementing it in a way that makes sense.
Essentially I have an Array with numbers between 1-4 and each number corresponds to a button getting let up.
for(let i = 0;i < arr.length;i++){
view.renderPane(arr[i]) //All this does is set the .css
view.renderPane is pretty simple:(I have a separate function that clears(sets opacity back to .5) it, but if possible i'd like to just put that in here.
renderPane(pane){
$("."+pane).css("opacity", "1");
console.log("Activating Pane "+ pane)
}
So I tried setting up a timeout thinking I could call the renderPane within the timeout, but all it did was set up a bunch of timeouts that basically fired off after X seconds (or milliseconds). Is there a way I can call the renderPane(pane) function every 1 second (to set up a delay) inside this for loop? or will I need to set up something else?
No need to use a loop, just create a function which continuously schedules itself with setTimeout until it's done — in this case, it removes an item from the array in each call and stops when the array is empty:
(function callee() {
view.renderPane(arr.shift());
if (arr.length)
setTimeout(callee, 1000);
})();
Example: https://jsfiddle.net/2fwht35d/
There are many other ways to implement this behaviour, but this should give you a good starting point.

JavaScript Div Annimation

I would like to know if there is any specific way to get javaScript code to stop executing at some point so as to allow another called function to execute, for example in a sorting algorithm using Div's you call a function which annimates the swapping of the two Div's so you can visually see the sort taking place. I have tried using the setTimeout(c,t); however it does not seem to be be waiting and the Divs do not seem to be moving, if I however place an alert(""); within the moving code it seems to allow the move to take place with thousands to alerts popping up.
The code I have is as follows:
var q;
var w;
function move(x,y)
{
q = x.style.top; // Keep a reference to the Top divs top element
w = y.style.top; // Keep a reference to the Top divs top element
doMove(x,y);
}
function doMove(topDiv, bottomDiv)
{
//alert("in doMove " + topDiv);
topDiv.style.top = parseInt(topDiv.style.top)+2+'px';
bottomDiv.style.top = parseInt(bottomDiv.style.top)-2+'px';
//alert("hi");
if(bottomDiv.style.top != q && topDiv.style.top != w) // Check if the Top and Bottom divs have finally swapped
{
setTimeout(doMove(topDiv,bottomDiv),20); // call doMove in 20msec
}
}
One problem with your code is that in this line:
setTimeout(doMove(topDiv,bottomDiv),20);
You are calling doMove immediately and passing the value undefined as the first parameter to setTimeout. Not entirely sure that the following will solve your problem, but I would recommend trying this:
setTimeout(function() { doMove(topDiv,bottomDiv); }, 20);

not looping through all items in array

this.draw = function() {
console.log(this.buttonList.length);
for(a = 0; a < this.buttonList.length; a++) {
console.log(this.buttonList.length, a);
this.buttonList[a].draw();
}
};
So I have this function within an object, and it's not working the way I expected it to. When I run it with the above console.log statements, it logs this on the console:
2
2 0
This seems to tell me that my for loop is not looping through every item on the array, and I've been scratching my head over why that would be for a quite a while now. Does anyone know why it's only performing the action for a = 0?
edit: I don't know if this makes a difference, but this function is called about 60 times every second.
Adding var would probably fix it :
this.draw = function() {
console.log(this.buttonList.length);
for(var a = 0; a < this.buttonList.length; a++) {
console.log(this.buttonList.length, a);
this.buttonList[a].draw();
}
};
There's very probably another point of your code where you change a. You should be careful with the variable declarations.
There are atleast three possibilities for the behavior:
a is overwritten (as per dystroys answer).
All elements in buttonList don't have a draw function.
this in the function definition of draw is an element in the buttonList.
The first two possibilities are easy to fix but the third one depends on what your intentions are, i.e. what do you wish to accomplish. To fix it we need more information.
Any one of the three possibilities (or combinations of the possibilities) could account for the behavior.
The first possibility is explained by dystroy.
The second possibility will stop excecution if an element doesn't have a draw function. In this case it seems to be the first element.
The third possibility will render in a stack overflow due to infinite recursion. The draw function is called over and over again just logging to console 2 then 2 0 until all the stack is consumed at which point the execution stops.

window.setInterval possible scope issue?

Thanks for taking the time to read this post. Finally built up enough courage to ask a question here :) Hope I ask my question in the correct way.
My problem is that I am trying to randomly animate "squares" around a page but am having an issue with the setInterval method.
You can find it here http://jsfiddle.net/xEMXh/
In the Init function I am trying to go though each ghost element and set it a interval function that will then make it animate in a random direction every X seconds.
for (ghostCount = 0; ghostCount < ghosts.length; ghostCount += 1) {
var speed = LesMccutcheon.GhostHunter.GetSpeed($(ghosts[ghostCount]).attr('data-speed')),
activeGhost = ghosts[ghostCount];
window.setInterval(function() {
LesMccutcheon.GhostHunter.MoveInDirection(activeGhost);
}, speed);
}
What is happening is only the last "ghost" element is animating. I know this is because in the for loop I am overriding the variable and by the time the first interval is called activeGhost is the last set in the for loop.
I tried using ghosts[ghostCount] directly in the set.Interval but it seems set interval cannot access this. I tried setting it to a variable inside the set.Interval anom function but it logged as undefined.
My only other half baked idea is to try and set an incremental var identifier but that seems quite counter productive and not a good way to go.
Thanks in advance for any advice!
Les
in your code the variable activeGhost will be overwritten for each loop.
just put the calling of setInterval into a closure like this
( function (activeGhost) {
window.setInterval(function() {
LesMccutcheon.GhostHunter.MoveInDirection(activeGhost);
}, speed);
} ( activeGhost) );
this way the reference to the correct element should be kept.

Categories