JavaScript Velocity do not wait until animation finishes - javascript

I am using JavaScript with the VelocityJS library to animate a pointer on my screen. The thing is that I get my input for how many degrees I have to rotate the pointer way more often than it can process.
The code that I have right now is:
function changePointer(msg){
kmh = parseInt(msg.payloadString);
degreesToTurnTo = Math.round(kmh * stapgrote);
$("#pointer").velocity({
rotateZ: degreesToTurnTo+"deg"
});
console.log(degreesToTurnTo);
}
The function is getting called about 5 times a second, but 1 animation already takes about half a second.
So my question is, how can I make an if statements that checks if the previous animation is ready (so that I can update it again once its finished). Or how can I cancel the current animation and start the next one (this method would be preferred since I am making a speedometer).
Thanks in advance!
With kind regards,
Mats de Waard

From: http://velocityjs.org/#stop
/* Prior Velocity call. */
$element.velocity({ opacity: 0 });
/* Later, midway through the call... */
$element
/* Stop animating opacity. */
.velocity("stop")
/* Animate opacity back to 1. */
.velocity("reverse");
So in your case something like:
$("#pointer")
.velocity("stop")
.velocity({
rotateZ: degreesToTurnTo+"deg"
});

Related

JS spinner only shows after action completes

This is a pretty consistent issue we've been struggling with for quite some time.
The page uses the fgnass spinner. The page is built on angular. When performing any kind of lengthy dom manipulation, I try and call the spinner, then perform said dom manipulation (for instance, calling pagination or search on rather large data sets). The actions can take a few seconds, thus the reason for the spinner: so the user knows stuff is happening, and to wait.
What I try to do is.
function callSpinner()
{
j$("div[class^='ui-dialog']").addClass('dialog_spinner');
j$("div[class^='ui-dialog-buttonpane ui-widget-content']").css("display", "none");
j$('#progressSpinner').dialog('open');
}
function closeSpinner()
{
j$('#progressSpinner').dialog('close');
j$("div[class^='ui-dialog']").removeClass('dialog_spinner');
}
This is using the angular pagination lib by Michael Bromley found here. This is happening inside the scope.setCurrent function of his library.
scope.setCurrent = function(num) {
callSpinner();
paginationService.setCurrentPage(paginationId, num);
closeSpinner();
}
That said, it occurs with a standard Angular filter as well.
This is the createSpinner method called on page creation (and I also launch the spinner once on page load)
function CreateSpinner()
{
// initialize spinner.
var opts = {
lines: 13, // The number of lines to draw
length: 15, // The length of each line
width: 5, // The line thickness
radius: 15, // The radius of the inner circle
corners: 1, // Corner roundness (0..1)
rotate: 0, // The rotation offset
direction: 1, // 1: clockwise, -1: counterclockwise
color: '#E68A2E', // #rgb or #rrggbb or array of colors
speed: 1, // Rounds per second
trail: 60, // Afterglow percentage
shadow: false, // Whether to render a shadow
hwaccel: false, // Whether to use hardware acceleration
className: 'spinner', // The CSS class to assign to the spinner
zIndex: 2e9, // The z-index (defaults to 2000000000)
top: '50', // Top position relative to parent in px
left: '30' // Left position relative to parent in px
};
var target = document.getElementById('progressSpinner');
$spinner = new Spinner(opts).spin(target);
j$("div[class='ui-widget-overlay ui-front']").addClass('overlay_style1');
}
And here's the HTML for the spinner tag I'm targeting.
<div id="progressSpinner" title="Progress" style="display: none; background-color: #000000; z-index: 1200; opacity: 0.8; padding: 0;"></div>
What actually happens though, is it fires off the pagination action, and waits to call the spinner until after the pagination process has finished. So the page just does nothing, the pagination finishes and the form is updated, then the spinner launches, then it closes.
As I said, I create the spinner on page load, then call the callSpinner function while the page is prepared. That works fine.
I can call callSpinner at any time, and it works fine as well.
I can even open the spinner in the console, then trigger the pagination click, and the spinner keeps spinning.
After various attempts at doing different things, I've finally got it working. There was never, at any point, anything specifically wrong with my code. If I put debug breaks at each code line for
callSpinner();
paginationService.setCurrentPage(paginationId, num);
closeSpinner();
everything works how it should.
I finally worked out that what's happening is the browser takes all 3 lines of code at once. And it decides it's more important to run the setCurrentPage function above everything else. So it paginates the entire thing, then it'll run callSpinner(); Then it immediately runs close spinner.
My solution:
callSpinner();
setTimeout(function () {
scope.$evalAsync(
function( scope ) {
paginationService.setCurrentPage(paginationId, num);
closeSpinner();
}
);
}. 200);
Reasoning: As near as I can tell, by putting the pagination call into a timeout with a short delay, it makes sure the callSpinner(); executes before doing anything else.
Originally, I just had the timeout, but as soon as the code in the timeout was called, it would trigger the closeSpinner(); line first, then do the pagination call. So I used Angular's $evalAsync on it, and that got it going right.

Toggle between two loops

As a way to learn more about jQuery, I'm trying to make a function that will scroll to the bottom of the page, back to the top and then start again in an infinite loop.
so far I have got this
var scroll = $(document).scrollTop();
setInterval(function(){
scroll += 5;
$(document).scrollTop(scroll);
}, 10);
This will scroll to the bottom of the page.
When it hits the bottom it needs to set a flag, maybe var direction = 1
where 1 is down and 0 is up.
Now I need to add something like
if(direction){
// scroll down
} else {
// scroll up
}
So I the IF would constantly check the value of direction and increment the scroll var by either += 5 or -=5
Does that sound logical or is there a much simpler way to achieve this?
EDIT
Here is a working version of somethinghere's suggestion
https://jsfiddle.net/Panomosh/evkxou3e/
You should use jQuerys callback to create an infinitely recursing function. Just add a function after the declaration in your animate function, and then call the same function, but invert the passed boolean.
Also, animate will do this incrementing very nice and smoothly for you!
function scrollTopOrBottom(top){
if(top) $("body, html").animate({scrollTop: 0}, function(){
scrollTopOrBottom(false);
});
else $("body, html").animate({scrollTop: $("document").height()}, function(){
scrollTopOrBottom(true);
});
}
scrollTopOrBottom(false);
Update: As mentioned, this could create a * * ahem * * Stack Overflow, but the question is not concerned with that at this point. If you want to be safe, use a stop() after each $("body, html") statement to stop the call from proceeding if another one is in progress, therefore deferring overflow.
Note: You could also wrap the if statement in {} but since it's one statement I find it a bit more legible, more sentence-like than code-like. But thats preference.
You could set the value of direction to be either 1 to scroll down or -1 to scroll up.
Then when changing the value of scroll you can do something like:
scroll += 5 * direction;

issue in nesting timeline : GreenSock for javascript

I am nesting timeline.
code is like:
timeLine.to(obj1,1.2,{css:{display:"block"}})
nestedTimeline1 = new TimelineMax({repeat:1});
// initially obj2 is with opacity :0
nestedTimeline1.append(TweenLite.to(obj2,1.4,{css:{opacity:1,left:187,bottom:108}}))
nestedTimeline1.append(TweenLite.to(obj2,.5,{css:{opacity:0}}),-.8)
timeLine.append(nestedTimeline1);
when i do:
timeLine.totalProgress(0);
my animation will start from first. But the issues is obj2 opacity will not be reset to 0.
i am not able to understand why this issue is coming?
any solution will be greatly appreciated..
Lets start with the first line.
You cannot animate to display:block - There's no numerical value to animate. You can animate from opacity:0 to opacity:1 just fine.
Now, lets think about the next problem.
You're attempting to animate opacity to 1 over 1.4 seconds.
Your next tween animates the same object from whatever to 0 over 0.5 seconds, with an offset of -0.8 seconds.
I'm not sure if you see the error here, but lets break it down in to a visual representation.
-------------------------------------------------- <-- Tween 1
--------------- <-- Tween 2
You see, Tween 2 finishes before Tween 1, since you pushed it back in the timeline 0.8 seconds and it only runs for 0.5 seconds. So Tween 1 now has that final 0.3 seconds to animate back to opacity:1
Also as a side note, you can use the convenience methods rather than .append(TweenLite...
nestedTimeline1.to(...) does the same thing.

Animating a div disappearance, how to smooth that?

I've been trying to animate a Dashboard Widget's div disappearance, but it just brutally goes "poof" (as in, disappears as expected, only instantly).
function removeElement(elementId)
{
duration = 9000; // The length of the animation
interval = 13; // How often the animation should change
start = 1.0; // The starting value
finish = 0.0; // The finishing value
handler = function(animation, current, start, finish) {
// Called every interval; provides a current value between start and finish
document.getElementById(elementId).style.opacity = current;
};
new AppleAnimator(duration, interval, start, finish, handler).start();
interval = 1;
start= "visible";
finish = "hidden";
duration = 9001;
handler = function(animation, current, start, finish) {
document.getElementById(elementId).style.visibility="hidden";
};
new AppleAnimator(duration, interval, start, finish, handler).start();
}
I expected this to "disappear" the div a millisecond after its opacity reaches zero, but for a not so obvious reason (to me), it just disappears immediately. If I comment out the second animation code, the div fades out (but it's still active, which I don't want).
All solutions I've yet seen rely on using JQuery and wait for the event at the end of the animation, is there another way to do that, other than JQuery?
If you are looking for a pure javascript solution it probably needs a good understanding of how javascript event work and basically about javascript language. As reference you should check this question on CodeReview
But as I think the best solution for you and not to rely on jQuery is to checkout CSS3 animations. Even if they are not supported by all browsers you could use Modernizer to fill polyfills for animations.
My favorite CSS3 Animation library is Animate.css. It's pretty neat and gives you a variety of demos in the page.
You'll first have to choose an animation and add it to your css stylesheets. Then have another custom class that contain everything about the animation.
.disappear{
-webkit-animation-duration: 3s;
-webkit-animation-delay: 2s;
-webkit-animation-iteration-count: infinite;
}
Then you could use javascript events to toggle in classes to your Elements. Below is how you add a class to an element.
var animationObject = document.getElementById("poof");
animationObject.className = animationObject.className + " disappear";
If you need more help regarding javascript of how this should be done check out this answer.
Hope this helps...
I found it: AppleAnimator possesses animator.oncomplete: A handler called when the timer is complete.
In my case:
var anim = new AppleAnimator(duration, interval, start, finish, handler);
anim.oncomplete= function(){
document.getElementById(elementId).style.visibility="hidden";
};
anim.start();
The Apple documentation actually calls "Callback" the animation code itself, and "handler" the callback, which makes it a bit hard to realize at first.
Thanks frenchie though, the "YourCallbackFunction" made me realize I was missing something related to callbacks :D

Would like to understand the Animate function (calculation and stepping)

I would like to know how does the jQuery .animate() function work? - calculation and stepping (how much it jumps)
When the animation starts, a timestamp is taken. Then everytime a step triggers (depends on browser and how much stuff is going on), it is calculated how much time has passed since the animation started and the progress is calculated from that.
For example, animation started at 1322338364714, and the animation is supposed to last 5000ms. Once a step is triggered the progress is calculated like so:
Get current time, say 1322338366714.
Normalize = 1322338366714 - 1322338364714 = 2000
Progress is 2000 / 5000 = 0.4 = 40%. So a div that is being animated from 0px to 100px, gets 40px height.

Categories

Resources