I'm using some animation using a function, let say, animateDiv(), and to which I'm assigning in an interval:
setInterval(function(){
stopDiv();//first stop animation
if(something == anotherthing){
doSomething();// it's just about to finish the animation
}
//now using animate
animateDiv();//finish animation from first to last position smoothly
},0);
If I don't use if condition and use doSomething() method directly, it doesn't hamper the animation i.e. smoothly run the animation.
With guess of my eyes there's 100ms gap between stopDiv() and animateDiv() because of checking for something == anotherthing even after this check return false.
So, how should I manage my code? What time does it take to output the result of check between two variables?
Related
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.
I am learning JavaScript and have been developing a simple game that is essentially a balloon that you can move around on the screen. I managed to do keypresses etc with a lot of help and the balloon moved about just perfectly.
I now want to simulate gravity, by having the balloon move one pixel down the screen if the balloon image was above a value, i tried to do this with the following do while statement:
var balloon = document.getElementById("balloon");
var bottom = parseInt (balloon.style.bottom, 10);
do {
balloon.style.bottom = bottom + 50 + 'px';
}
while (bottom = bottom > 600) // Gravity
What I want this to do, is to check the code is working by making the balloon move up the page 1 pixel if the bottom value is less than 600.
I have stripped out all the code I used to make the balloon move.
If I could just see the balloon move slowly up the page I would be very happy, because then at least I know I can just switch the values round when I've added the movement back in.
The other answers address the issue of attempting an animation with an explicit loop. As they have pointed out, you should use timers.
Because it seemed like fun, I made you a simple example of how to use a timer to animate a balloon falling:
http://jsfiddle.net/dmuu9w97/
The key code is the following:
// Make balloon fall 1px every 10ms
setInterval(function() {
var bottom = getBalloonBottom();
if (bottom > 0)
balloon.style.bottom = bottom - 1 + "px";
}, 10);
For your while loop condition should be (bottom>600) . No need for '='
You are loading the variable bottom outside the loop. It will never change. If it is 610 at the start of the loop it will remain 610 because it is assigned only in line 2 of your code
While loop should probably be ....bottom = (bottom - 1) + 'px';
If you write a while loop like this, it will execute 10 times immediately and your baloon will be always stuck in 600
To solve 'stuck at 600' problem, you should use a timer:
Think about "how fast should the balloon fall". Then you can come up with some number like "5 pixels in 100 milliseconds".
Then write a function... call that function on a timer.
Check the setTimeout function here...
setTimeout method
It's not impossible to do with a do loop but I think you ought to abandon this explicit loop in favor of javascript's timer/timeline. Look into how to use window.setTimeout() where the body of your do loop becomes the body of the callback function AND a trailing call to window.setTimeout() passing the callback again with a delay of 1000/your-chosen-framerate milliseconds. Then you can also process keypress events in their own handlers for intentional movement.
If you use an explicit loop, you'll only get gravity because the loop should never end (just as gravity never stops pulling) and therefore the browser will never have a chance to call the keypress event handler.
Your timeout callback runs once, queues itself again, and terminates. That gives control back to the browser's javascript engine to process events or, if nothing else, run the callback function again after the requested delay.
requestAnimationFrame may be more appropriate than setTimeout in modern JS implementations. It usually leads to a smoother result for animations.
I have programmed a video player in Javascript and I am trying to implement a rewind / forward functionality.
The aim is that the video will rewind in when the button is held down. I programmed a version of this which would rewind once when the button is clicked but then you have to keep clicking it to rewind continuously.
So far I have done this:
HTML
<video id="media" width="600" height="400" preload="none">
<source src="files/Best of 60s.m4v">
</video>
<input type="button" id="skipTrackBackward" value="Backward" onmousedown="rewind()" onmouseup="stoprewind()"/>
Javascript:
var skipB
function initiate(){
mmedia = document.getElementById('media');
skipB = document.getElementById('skipTrackBackward');
function rewind(){
while (!mmedia.paused && !mmedia.ended){
for (var i = mmedia.currentTime; i != 0; i--){
mmedia.currentTime=i;
}
}
}
function stoprewind(){
mmedia.play();
}
The above code causes my Chrome tab to crash so obviously I have done something very wrong! But my understanding is that I only want the rewind function to start provided the video has not reached its end or has been paused. So while it is in that state it should run the for loop which takes into account the currentTime which has elapsed and subtract 1 second while the mouse is pressed down (currentTime takes integers which are interpreted as seconds). It should keep updating currentTime as long as it has not reached 0 seconds.
The above code has been minimised for convenience. Any suggestion greatly appreciated.
I think you've created either an infinite loop or your setting mmedia.currentTime to a bogus value.
First lets cover trouble shooting. See what the console outputs, Add some console.log statements to see what the values are as it runs and what the values are just before it crashes, step through the code in the debugger (use conditional breakpoints to filter out the noise).
Now code analysis. Try replacing the variables with hard coded values and see if the logic pans out:
while (!mmedia.paused && !mmedia.ended) {
^1 ^2 ^3
Why the while? is there a case where you need to run the for loop until mmedia.paused and mmedia.ended?
When does this variable change to break out of the loop?
Or this variable?
So when the for loop executes there is nothing to cause mmedia.paused or mmedia.ended to be changed from false to true and that is an infinite loop.
Also you check that i != 0 is it possible for i to be < 0? And if so will mmedia.currentTime handle values less than 0?
Last but not least if you were to have a break out of the while / for loop it is in a blocking process. This means that if you rely on user interaction to flip one of the cancel flags it will never happen because the thread is waiting for the while / for loops to finish before registering that the user did something. If the infinite loop was fixed one click would prevent the pause / stop button from being clicked till it reached the beginning (obviously this is silly since you could just set currentTime to 0 in the first place). Another effect is that you won't see the rewind process because it won't update the display till the thread is finished executing code.
What you will need it to rewrite the logic in a non-blocking fashion. This is called asynchronous code and is a lot more complicated then a simple loop.
var stopRewinding;
function rewind() {
var timeout = 100;
stopRewinding = false;
if (mmedia.paused || mmedia.ended) {
console.log("Media state unable to rewind");
return;
}
function worker() {
if (stopRewinding || mmedia.currentTime <= 0) {
return; // All done so get outa here
}
mmedia.currentTime--;
setTimeout(worker, timeout);
}
worker();
}
Now you can interrupt the loop by setting stopRewinding to true or when the currentTime reaches 0.
You can then either have a button or use the mousedown and mouseup events to trigger rewind() and stopRewinding = true.
I am trying to create a scenario where I have two variables (or more) both assigned to their own setInterval object and each setInterval object has a different function and a different millisecond value. The goal is to create a rhythm between the two by launching functions that play two different audio files repeatedly.
The current problem I've come across is this:
If one set interval is set to 1000 and the other is set to 500 each one doesn't start immediately. The millisecond delay is part of the start time. I want to know how to omit the delay on the start time so that both functions launch immediately but then they each keep there respective interval times.
The "logic" I've come up with so far is something along the lines of creating a function that immediately plays audio with no millisecond value and then have another function that is assigned to setInterval which begins playing x number of millisecond earlier on the next "beat" to make up the difference. I'm curious if the logic seems sound or if this is a problem in which a "conventional" javascript solution exist that I don't know about.It seems like there is an easier way.
I haven't begun coding yet albeit I didn't want to dig myself a hole before I have to if someone already has a fix for this.
Thanks
I avoid setInterval. Instead, i use setTimeout with such a pattern:
function someThing() {
// do something ...
setTimeout(someThing, 2000);
// or do something after setting the timeout ...
}
// either delay the start:
// setTimeout(someThing, 1000);
// or start right away
someThing()
But if you really want to use setInterval then a similar pattern works:
function someThing(firstTime) {
if (firstTime === true) {
console.log('setting interval for someThing');
setInterval(someThing, 1000);
}
console.log('someThing called');
}
someThing(true);
I'm creating a game with jQuery, and I want my character to move automatically until it hits a boundary. Here is my movement code in right direction:
if (e.keyCode === 39 && (p1_left < 784)) {
$('#p1').rotate(0);
setInterval ( function() {
$('#p1').animate( { left: "+=16px", }, 50); }, 50);
}
This moves my character indefinetely to the right, and I haven't figured out myself how to create a stopper.
EDIT: Updated code snippet, Added jsfiddle http://jsfiddle.net/BjCeq/
You never actually increase pl_left so the loop will just run forever:
while (p1_left <= 784) {
pl_left+=16;
$('#p1').css('left', p1_left);
}
However, this is not going to animate the movement of your character, it will appear to just jump to the end point. For this reason it is kind of pointless to loop. What you probably want is either to use setTimeout to move every second one position or something. Or, you could use animate with a callback function:
function moveLeft(theID){
$(theIE).animate({...},1000, function(){
if(/* keep moving */){
move_left(theID);
}
}
}
What you need is code that's continually called. Your code, as you've written it, is called once, and it performs all of its DOM manipulation at once. What you need is a setInterval or a setTimeout to trigger your code to call itself a certain number of milliseconds in the future, incrementing the css property each time. The easiest way to accomplish this is to simply use jQuery.animate, which runs those methods internally.
var $p1 = $('#p1');
if (e.keyCode === 39 && (p1_left < 784)) {
$p1.rotate(0);
$p1.animate({ 'left' : 784 });
}
Check out the jQuery animate docs for more information, including how to set options and run a callback function with each frame of the animation: http://api.jquery.com/animate/.