Page Freezes with move.js animation loop - javascript

The goal of this is to have this script run until a certain condition is met. In this case the condition would be that say a widget on the site has completed sending an Ajax request and received and processed a response.
Issue is that the page freezes up whenever the function load() is run.
var animateWrap = u(document.getElementsByClassName("process_transaction_wrapper"));
var i = 0;
function load(){
animateWrap.append("<div class='loader'></div>");
// Create Loading Object
move(".loader")
.set("width", "25px")
.set("height", "25px")
.y(75)
.set("background-color", "#ccc")
.end();
while(i < 1) {
move(".loader")
.y(0)
.rotate("180")
.duration("2s")
.end(function(){
move(".loader")
.y(75)
.rotate("360")
.duration("2s")
.end();
});
}
}
function endLoad(){
i++;
}

You are executing move() very repetitively at an extreme pace inside that loop. That is going to cause a freeze. You want to run a recursive timeout or a simple interval, preferably after your .duration(2s) ends.
var animateWrap = u(document.getElementsByClassName("process_transaction_wrapper"));
var timer = null; //initialize a timer variable to hold timeout
function load() {
animateWrap.append("<div class='loader'></div>");
// Create Loading Object
move(".loader")
.set("width", "25px")
.set("height", "25px")
.y(75)
.set("background-color", "#ccc")
.end();
callMovement(); //start movement OR call this in the end() function of the initial loading object
keepMoving(); //start continuous movement
}
function keepMoving() {
//assign a timeout to the timer
timer = setTimeout(function () {
callMovement();
keepMoving(); //call same function again after 2000ms. You could probably call this inside .end() on this animation library of yours to preserve accuracy.
}, 2000);
}
function callMovement() {
move(".loader")
.y(0)
.rotate("180")
.duration("2s")
.end(function () {
move(".loader")
.y(75)
.rotate("360")
.duration("2s")
.end();
});
}
function endLoad() {
clearTimeout(timer); //call this to stop recursion
}
Wait are you creating a loading spinner? You can easily make this on css and toggle movement and displays by simple class manipulation. It is miles easier than manually doing such a small task in JS

Related

Redirect with inactivity

My objective is to keep a user in a view as long as he/she keeps clicking a button within a certain lapse.
I'm using Rails and was exploring a solution via an embedded JS in the pertinent view.
So far I'm able to set a time after which the user will be redirected to root path with the following script:
var delayedRedirect = function (){
window.location = "/";
}
var delay = 10000;
$(document).ready(function() {
setTimeout('delayedRedirect()', delay);
});
I've been trying to write a function that resets the value of 'delay'or that calls the setTimeoutFunction again.
$('#btn-persist').click(function() {
delay = 3000;
// or calling again setTimeout('delayedRedirect()', delay);
});
But I noticed that changing the variable won't affect the setTimeout function that has already been called.
I've also tried to use the clearTimeout function as below without success
var delayedRedirect = function (){
window.location = "/persists";
}
var delay = 3000;
var triggerRedirect = function() { setTimeout('delayedRedirect()', delay);
}
var stopRedirect = function (){
clearTimeout(triggerRedirect);
}
$(document).ready(function() {
triggerRedirect();
$('#btn-persist').click(function() {
stopRedirect();
});
});
I wonder why this may not be working and if there's any other way to stop the execution of the setTimeout function that has already been called so I can call it again to effectively reset the time to the original value of 'delay'.
At the same time, I don't want to stop any other JS functions that are running in parallel.
Do you see a better solution to achieve this?
The main problem why clearTimeout is not working. because you are clearing a anonymous function instead of a setTimeout variable
change this
var triggerRedirect = function() { setTimeout('delayedRedirect()', delay);
}
to this
var triggerRedirect = setTimeout('delayedRedirect()', delay);
Edit:
also change this (if you want to restart the inactive redirect trigger)
$('#btn-persist').click(function() {
stopRedirect();
});
to this
$('#btn-persist').click(function() {
stopRedirect();
triggerRedirect();
});

AngularJS: reset $timeout for each page switch

I'm working on my first AngularJS project and I'm working on a timeout that redirects the user to the startpage after a few minutes if they haven't clicked on anything. timeout is called on each page load to restart the timeout.
But the my problem is that restart() is called multiple times. One time for each page/view load. I use ngRoute.
For example if has clicked on three pages, timeout() has now been called three times and when the $timeout reaches the time, restart() is called three times.
myapp.controller(..., [...], function(...) {
function restart() {
$location.path("/slide/1");
}
function timeout() {
var timeoutHandle = $timeout(function() {
$timeout.cancel(timeoutHandle);
restart();
}, timeoutTime);
}
timeout();
}
Try to use this code:
var redirectTimeout;
var redirect = function() {
$location.path("/slide/1");
}
$timeout.cancel(redirectTimeout);
redirectTimeout = $timeout(function() {
var timeoutTime = 5000 // five seconds
redirectTimeout = $timeout(redirect, timeoutTime);
});
Here is the JSFiddle
Wouldn't it be better to put this kind of functionality inside a factory?

Prevent repeated GET within loop when using setTimeout

I am trying to run a javascript that would set background color of a page as red, wait seconds and then get a value from a webpage and then turn green and then stay green for that many seconds before becoming red again and repeating indefinitely.
Am using JQuery GET to get the webpage.
My code
<script>
function g() {
document.body.bgColor = 'green';
}
function r() {
document.body.bgColor = 'red';
}
$(document).ready(function(){
while(1)
{
$.get("http://localhost:8080/t.html", function( data ){
setTimeout'g()',10000);
setTimeout('r()',data*1000);
});
}
});
</script>
Problem : Somehow the seTimeout is causing the loop to continue. By the time the page waits a few seconds hundreds of GET requests are generated. I need the full process to freeze while the code is waiting the given time.
My browser is detecting this continuous loop due to heavy activity and asking to kill it.
Please help me sort this out.
Try this,
$(function(){
r();
});
function r(){
var timeOut = 5000;
if(document.body.bgColor=='green'){
document.body.bgColor = 'red';
timeOut = 10000;
}else{
document.body.bgColor = 'green';
}
setTimeout(r,timeOut);
}
DEMO: http://jsfiddle.net/Hnuy8/
setTimeout will not freeze your while function, because its async. It will just wait and execute g() after the given time.
setInterval(function() {
$.get("http://localhost:8080/t.html", function( data ){
if(data=="green") g();
else r();
});
},10000);
this would execute the GET-Request every 10 seconds and set the background to green, when data is green, otherwise to red.
I'm not completly understanding what you want to achieve, so you would need to modify this a bit.
please have a look
<script>
function g() {
document.body.bgColor = 'green';
}
function r() {
document.body.bgColor = 'red';
}
$(document).ready(function(){
function changeBG()
{
$.get("http://localhost:8080/t.html", function( data )
{
setTimeout('g()',10000);
setTimeout('r()',data*1000);
changeBG();
});
}
changeBG();
});
</script>

How to stop a requestAnimationFrame recursion/loop?

I'm using Three.js with the WebGL renderer to make a game which fullscreens when a play link is clicked. For animation, I use requestAnimationFrame.
I initiate it like this:
self.animate = function()
{
self.camera.lookAt(self.scene.position);
self.renderer.render(self.scene, self.camera);
if (self.willAnimate)
window.requestAnimationFrame(self.animate, self.renderer.domElement);
}
self.startAnimating = function()
{
self.willAnimate = true;
self.animate();
}
self.stopAnimating = function()
{
self.willAnimate = false;
}
When I want to, I call the startAnimating method, and yes, it does work as intended. But, when I call the stopAnimating function, things break! There are no reported errors, though...
The setup is basically like this:
There is a play link on the page
Once the user clicks the link, a renderer's domElement should fullscreen, and it does
The startAnimating method is called and the renderer starts rendering stuff
Once escape is clicked, I register an fullscreenchange event and execute the stopAnimating method
The page tries to exit fullscreen, it does, but the entire document is completely blank
I'm pretty sure my other code is OK, and that I'm somehow stopping requestAnimationFrame in a wrong way. My explanation probably sucked, so I uploaded the code to my website, you can see it happening here: http://banehq.com/Placeholdername/main.html.
Here is the version where I don't try to call the animation methods, and fullscreening in and out works: http://banehq.com/Correct/Placeholdername/main.html.
Once play is clicked the first time, the game initializes and it's start method is executed. Once the fullscreen exits, the game's stop method is executed. Every other time that play has been clicked, the game only executes it's start method, because there is no need for it to be initialized again.
Here's how it looks:
var playLinkHasBeenClicked = function()
{
if (!started)
{
started = true;
game = new Game(container); //"container" is an empty div
}
game.start();
}
And here's how the start and stop methods look like:
self.start = function()
{
self.container.appendChild(game.renderer.domElement); //Add the renderer's domElement to an empty div
THREEx.FullScreen.request(self.container); //Request fullscreen on the div
self.renderer.setSize(screen.width, screen.height); //Adjust screensize
self.startAnimating();
}
self.stop = function()
{
self.container.removeChild(game.renderer.domElement); //Remove the renderer from the div
self.renderer.setSize(0, 0); //I guess this isn't needed, but welp
self.stopAnimating();
}
The only difference between this and the working version is that startAnimating and stopAnimating method calls in start and stop methods are commented out.
One way to start/stop is like this
var requestId;
function loop(time) {
requestId = undefined;
...
// do stuff
...
start();
}
function start() {
if (!requestId) {
requestId = window.requestAnimationFrame(loop);
}
}
function stop() {
if (requestId) {
window.cancelAnimationFrame(requestId);
requestId = undefined;
}
}
Working example:
const timeElem = document.querySelector("#time");
var requestId;
function loop(time) {
requestId = undefined;
doStuff(time)
start();
}
function start() {
if (!requestId) {
requestId = window.requestAnimationFrame(loop);
}
}
function stop() {
if (requestId) {
window.cancelAnimationFrame(requestId);
requestId = undefined;
}
}
function doStuff(time) {
timeElem.textContent = (time * 0.001).toFixed(2);
}
document.querySelector("#start").addEventListener('click', function() {
start();
});
document.querySelector("#stop").addEventListener('click', function() {
stop();
});
<button id="start">start</button>
<button id="stop">stop</button>
<div id="time"></div>
Stopping is as simple as not calling requestAnimationFrame anymore, and restarting is to call it it again.
ex)
var pause = false;
function loop(){
//... your stuff;
if(pause) return;
window.requestionAnimationFrame(loop);
}
loop(); //to start it off
pause = true; //to stop it
loop(); //to restart it
var myAnim //your requestId
function anim()
{
//bla bla bla
//it's important to update the requestId each time you're calling reuestAnimationFrame
myAnim=requestAnimationFrame(anim)
}
Let's start it
myAnim=requestAnimationFrame(anim)
Let's stop it
//the cancelation uses the last requestId
cancelAnimationFrame(myAnim)
Reference
I played around with the tutorial of a 2D Breakout Game where they also used requestAnimationFrame and I stopped it with a simple return. The return statement ends function execution if the value of return is omitted.
if(!lives) {
alert("GAME OVER");
return;
}
// looping the draw()
requestAnimationFrame(draw);
I would suggest having a look at the requestAnimationFrame polyfill gibhub page. There are discussions about how this is implemented.
So, after doing some more testing, I've found out that it was, indeed, my other code that posed a problem, not the animation stopping (it was a simple recursion after all). The problem was in dynamically adding and removing the renderer's domElement from the page. After I've stopped doing that, for there was really no reason to do so, and included it once where the initialization was happening, everything started working fine.

Other way to "wait" during javascript animation

i'm looking for another way to execute this code :
$.each($("#gallery > img"), function(index,curImg) {
setTimeout(function() {
clearCanvas();
cvsCtx.drawImage(curImg,0,0);
} , index*animationMs);
});
This code draw an image from my gallery to my canvas every animationMs .
But i would like to make it possible to stop the animation, with a "Play/stop" button, I can't do it this way...
Any idea or workaround ?? thank you !!
I can't test it. But you can stop animation by using a variable to hold the setTimeout function as following:
var x; // public var
....
x = setTimeout(......);
// To stop it use:
clearTimeout(x);
Hope this works for you
I find that creating timeouts in a loop is usually too hard to manage - you don't want to have to cancel multiple timeouts. Better to have the function doing the work call itself (indirectly) by setting a timeout just before it completes, because then you can put in a simple if test to decide whether to set the next timeout and continue your animation.
Perhaps a little something like this:
<input id="playPause" type="button" value="Play">
<script>
function initAnimation(animationMs, autoRepeat, waitForPlayButton) {
var currentFrame = 0,
$imgList = $("#gallery > img"),
paused = waitForPlayButton;
function drawNext() {
clearCanvas();
cvsCtx.drawImage($imgList[currentFrame++],0,0);
if (currentFrame >= $imgList.length) {
currentFrame = 0;
if (!autoRepeat) {
paused = true;
$("playPause").prop("value", "Play");
}
}
if (!paused)
setTimeout(drawNext, animationMs);
}
$("playPause").prop("value", waitForPlayButton ? "Play" : "Pause")
.click(function() {
this.value = (paused = !paused) ? "Play" : "Pause";
if (!paused)
drawNext();
});
if (!waitForPlayButton)
drawNext();
}
initAnimation(100, true, false);
</script>
If autoRepeat param is false the animation will run once and stop, but can be restarted via the button, otherwise (obviously) it just keeps repeating.
If waitForPlayButton is false the animation will start immediately, otherwise (obviously) it will start when the button is pressed.
Pressing the button will pause at the current frame.
(Not tested since I don't have a bunch of images handy, but I'm sure you get the idea and can fix any problems yourself. Or let me know if you get errors...)
var images = $("#gallery > img").clone(), interval;
function startLoop() {
interval = setInterval(function(){
var image = images[0];
clearCanvas();
cvsCtx.drawImage(image,0,0);
images.append(image);
}, animationMs);
}
$(".stop").click(function() {clearInterval(interval);});
$(".start").click(startLoop);
setTimeout return a timeoutID which can be given to clearTimeout as a parameter to stop the timeout from happening.
You can read more about this at: https://developer.mozilla.org/en/DOM/window.setTimeout
Good luck
It's not really an animation... but still:
$("#gallery > img").each(function(index,curImg) {
$(this).delay(index*animationMs).queue(function(next) {
clearCanvas();
cvsCtx.drawImage(curImg,0,0);
if (next) next();
});
});
Using jQuery queues like I did allows you to do .stop(true), on $("#gallery > img") or a single image and stop their "animation".
First you could add images to a javascript array variable (eventually global) and then call a function cycle() on that array for all its length.
You should put your setTimeout() call inside that function, assigning it to a variable: var t=setTimeout("cycle()",animationMs); and execute clearTimeout(t); when you want to stop the animation.
Of course you could also save in a variable the frame where you were when stopping the animation and restart exactly from that frame when pressing "play" button.

Categories

Resources