How to stop (in order to reverse) a fabricjs animation - javascript

I want to create a mouse rollover effect, like we used to see in flash websites - when the mouse rolls over an element it begins to animate, but if in the middle of the anim the mouse rolls out the animation would stop and run back.
I would like to achieve the same effect with fabric, but I can seem to find a way to stop the animation. For example:
rect.animate('top', '200', {
duration: 1000,
onChange: canvas.renderAll.bind(canvas),
onComplete: function() {
//callback code goes here
}
});
This will animate until the top value of the rect will become 200. Is there a way to stop animation before that?

You need to specify abort function.
rect.animate('top', '200', {
duration: 1000,
onChange: canvas.renderAll.bind(canvas),
onComplete: function() {
//callback code goes here
},
abort: function(){
return someConditionWhichAbortsAnimationWhenItsTrue;
}
});
The only problem is that abort was not passed in to the underlying fabric.util.animate, which I just fixed, so you'll need to use latest version :)

Related

TweenMax hover animation issue

I have a nagivation bar with li in my backbone application. I am creating a hover effect for the links. The effect is just a background image sliding to the hovered link and then going back to the original position.
For the animation, I am using TweenMax library. The way this works is:
First I initialize TimelineMax with a paused property like this:
this.animation = new TimelineMax({ paused: true });
then I work with these methods:
prepareToAnimate: function(to) {
this.animation.to(this.el, .5, { left: to });
return this;
},
animate: function() {
this.animation.play();
},
reverse: function() {
this.animation.reverse();
}
So basically, from outside my view I wanted to call movingElementView.prepareToAnimate(200).animate() on mouseenter and movingElementView.reverse() on mouseleave.
It is animating, but the animation is going crazy. It goes forward, then it goes backward, then jumps forward again. I checked the console and it seems to add up the duration and probably left property as well. Do I have to new up TimelineMax on every mouse event instead?

How to stop jcarousel animation?

I'm using jcarousel to animate an unordered list but since I need the animation to smoothly transition between items I'm setting the animation option to a very large integer, this works fine but I need to start the slide animation when I mouse over some links and stop it on mouse out, this is what I have so far:
$(function() {
function customCallback(carousel) {
$('.prev').hover(function() {
// Starts the back animation
carousel.prev();
}, function() {
// How to stop animation?
});
$('.next').hover(function() {
// Starts the forward animation
carousel.next();
}, function() {
// How to stop animation?
});
}
$('.list').jcarousel({
animation : 14000,
wrap : 'circular',
easing : 'linear',
buttons : false,
initCallback : customCallback
});
});​
But I don't know how to stop the animation on mouse out, here's a demo to illustrate this better: http://jsfiddle.net/hfuwM/1/
Can anyone point me in the right direction? Thanks in advance
EDIT: I found that using carousel.list.stop() on the mouseout callback stops the animation but then it doesn't restart when hovering the links again.

Multiple hover instances jQuery

I have a div to animate from the top to the bottom of another div. I'm currently playing w/ mouseenter/leave and JS animations w/ easing where its original state is up/top. I want to hover/mouseenter and have it move down and stay down if I mouseleave/hover off. When I hover again it will animate back to the top/start.
I initially used mouseenter/leave which obviously doesn't do what I need as I would like the state to remain the same upon mouseleave. So what function would be best for this need? I'm still learning the terminology and am stumbling over how to better phrase the question.
Code:
function init() {
mouseenter: function(){
$(".ltrP").stop(true, true).animate({
marginTop:"170px"
},
{
duration: 1000,
easing: "easeOutBounce"
});
},
mouseleave: function(){
$(".ltrP").stop(true, true).animate({
marginTop: "0px"
},
{
duration: 1000,
easing: "easeInBounce"
});
}
});
}
window.onload = init;
I've edited your piece of code, see the comments for explanation:
$(document).ready(function(){ // Runs when document is loaded
$(".ltrP").mouseenter(function(){ // Mouseenter event on the given object (.ltrP)
var goTo = $(this).css("marginTop") == '0px' ? 170 : 0; // When the current margin-top is 0px animate to 170px, otherwise animate it back to 0px
$(this).stop(true,false).animate({ // Changed the stop(true, true) to stop(true, false), looks nicer in my opinion
marginTop: goTo // Animate to the just set variable
}, 1000);
});
});
And see here a demo: http://jsfiddle.net/hnDmt/
(And the easing "easeInBounce" was not working for me, so I removed it. (Maybe a jQuery UI easing?))
You can rewrite your code this way:
$(document).ready(function(){
init();
});
function init() {
$.hover(function(){
$(".ltrP").stop(true, true).animate({
marginTop:"170px"
},
{
duration: 1000,
easing: "easeOutBounce"
});
},
function(){
$(".ltrP").stop(true, true).animate({
marginTop: "0px"
},
{
duration: 1000,
easing: "easeInBounce"
});
});
}
There are lots of ways to do this. Maybe the easiest to to conceptualize is by adding a class to the animated item. You want to write two separate mouseenter functions.
For the first function, trigger your down animation, and add a class to the entered item. Call the class "moveddown" or something obvious.
Then, write a second mouseenter function. When an item with the class is mousentered, animate it up, and remove the class.
Forget about jQuery hover for this. It's just a wrapper for mouseenter/mouseleave. It can cause problems. The jQuery docs warn about it. It's usually better to write mouseenter and mouseleave functions separately, especially when you're trying to do something tricky, like this.

Sensitivity of mouseOver in a Jquery simple FishEye script

After having troubles with a jquery fisheye plugin I've decided to develop a similiar script by myself. (It's also a good practice).
Anyway , I wrote 2 jquery functions based on the Animate() function.
minimizeBubble
return the bubble to its default size
maximizeBubble
make the bubble bigger , higher and display another picture as well (a
title for that bubble)
jQuery.fn.maximizeBubble = function(){
$(this).animate({
marginTop: '-300px',
width: '300px',
}, {
duration: 200,
specialEasing: {
width: 'linear',
},
complete: function() {
$(this).find("span").css("display" , "inline");
}
});
}
jQuery.fn.minimizeBubble = function(){
$(this).animate({
//top: '+=5',
marginTop: '0',
width: '80px',
}, {
duration: 100,
specialEasing: {
width: 'linear',
},
complete: function() {
$(this).find("span").css("display" , "none");
}
});
}
I also wrote the next code:
I know that the .each() function in this case is not neccessery because
there's only one big bubble at a time.
$(document).ready(function() {
//First , the middle one will be big as default.
$('#auto_big').maximizeBubble();
//mouseOver - make it big , onMouseout - Stay Big (do nothing)
$('.dock-item2').mouseover(function() {
//mouseOver on another bubble- minimize the other one and maximize the current
$('.dock-item2').each(function(){
$(this).minimizeBubble();
});
$(this).maximizeBubble();
});
});​
(A jsFiffle for my code: http://jsfiddle.net/T7gCL/1/)
The problem , as you can see at: http://jsfiddle.net/T7gCL/1/embedded/result/ that
when you move your mouse to the next bubble , all the bubbles are starting to "get crazy".
1.Do you know what's the reason for this behaviour?
2.How can I solve it?
3.do you have any suggestions of how to improve my code (for instance: instead of each())?
Part of the reason there is so much hopping around is that you're positioning the images absolutely and then resizing them. I'm not sure what the application calls for but I would try floating them for now. The animation behavior is like a chain reaction which makes me draw the hypothesis that when the image resizes it is propagating the onMouseover event to the images it is overlapping. The floating layout may fix this.
Update
This works better but might not be exactly what you're trying to do
$('.dock-item2').mouseenter(function(event) {
event.stopPropagation()
$(this).maximizeBubble();
});
$('.dock-item2').mouseleave(function(event) {
event.stopPropagation()
$(this).minimizeBubble();
});
You still need to rework the way you're organizing the images in their containing div

jQuery's stop() seems to be blocking animations that haven't been queued yet

How does jQuery's stop() actually work?
If you look here (http://jsfiddle.net/hWTT6/), when you hover over the main blue box it should fade to red, and when you hover off it should fade back. The problem is it will completely fade to red (and then back to blue) even if the mouse has hovered off before the first fade was complete. The problem can more clearly be seen with the slide effect. Hover over the slide "button" and the main box will slide to blue, hover off, it will slide back. But try hovering on and off and on and off, before the first animation has completed. You'll see that all four animations are carried out. I included both examples here to show it is not just a problem with one effect or something.
I thought this would be easily fixed by adding a stop before the animations, as shown commented out in the code. But, if I do this the current animation will stop and the following one will never start. Almost as though stop is blocking an animation that is occurring after the call to stop.
What am I missing here?
Thanks.
You are missing that .stop() accepts two arguments. Both boolean, indicating:
- clearQueue (first)
- jumpToEnd (second)
So by calling $('#foo').stop( true, true ).doSomeOtherStuff() you should get your desired goal.
Reference: .stop()
The problem is the CSS is getting messed up by stopping at arbitrary points.
The fadeIn(), fadeOut(), slideUp() and slideDown() move from the current state to a new one and then revert to that - not to the original CSS.
You need to fix the CSS back in to a usable state to continue with after the .stop(), or more clearly specify the animation targets.
As the others have said, you can get the CSS to the correct position, by ensuring that when you stop the animation, it jumps to the end of it, rather than leaving everything in an arbitrary state.
UPDATE:
Take a look at the code in this update of your demonstration: http://jsfiddle.net/hWTT6/5/
It might not be exactly how you want it to perform, but the trick, if you do not want the animation to run its course, is to get the animation back in to a state that it can continue from in the way in which you desire.
$(function() {
$('#fade')
.mouseenter(function() {
$('#fg_fade').stop().animate({ 'opacity': 0 }, 'slow', function() {
$('#fg_fade').css('height', '100%');
});
})
.mouseleave(function() {
$('#fg_fade').stop().animate({ 'opacity': 1, 'height': '100%' }, 'slow');
});
$('#slide_fire')
.mouseenter(function() {
$('#fg_fade').stop().animate({ 'height': 0 }, 'slow', function() {
$('#fg_fade').css('opacity', 1);
});
})
.mouseleave(function() {
$('#fg_fade').stop().animate({ 'height': '100%' }, 'slow', function() {
$('#fg_fade').css('opacity', 1);
});
});
});
You could set the stop() options to (true, true) so that you cancel all events in cue and jump to the end of the previous animation. look at the fiddle:http://jsfiddle.net/hWTT6/4/
The stop method can be called in the following difference ways:
.stop(true);
//Same as:
.stop(true, false); //Empty the animation queue only
//Or
.stop(true,true); // Empties the animation queue AND jumps to the end
//Default
.stop()
//Same as
.stop(false,false);
There may be a better way using .animate instead: Demo Here
$(function() {
$('#fade')
.mouseenter(function() {
$('#fg_fade').stop().css('height', '10em').animate({'opacity' : '0'}, 'slow');
})
.mouseleave(function() {
$('#fg_fade').stop().css('height', '10em').animate({'opacity' : '1'}, 'slow');
});
$('#slide_fire')
.mouseenter(function() {
$('#fg_fade').stop().css('opacity', '1').animate({'height' : '0'}, 'slow');
})
.mouseleave(function() {
$('#fg_fade').stop().css('opacity', '1').animate({'height' : '10em'}, 'slow');
});
});
This way the animation stops when you want it to and still runs the next animation.
The problem with doing .stop then slideUp/slideDown or fadeIn/fadeOut is that the animation can end prematurely and keep an incorrect height/opacity.
The problem is caused by the way fadeIn, fadeOut etc. work. You may expect them to fade between 0 and 1. However, in reality they fade between 0 and whatever the "baseline" opacity is. You can see this here:
http://jsfiddle.net/hWTT6/7/
You'll notice I set the initial opacity to .5. Now when I call fadeIn it does not fade all the way in to 1 it fades to my baseline of .5. Your problem occurs when you stop the animation prematurely, the "baseline" becomes whatever the opacity is at the time it is stopped. Now when you call fadeIn on mouseleave it tries to fade to this new baseline and finds it is already there. You can see this illustrated by going here:
http://jsfiddle.net/hWTT6/8/ (original, but with .stop)
If you place your mouse over slide and then remove it half-way through the animation, it will stop in the middle. Now place your mouse back over slide and wait for the animation to complete. If you now remove your mouse, you will see that it slides back down to the place where the first animation was stopped. That is because this is the new "baseline".
The way that you would solve this is actually to replace fadeIn, fadeOut, etc. with a more explicit animation. For instance, use fadeTo to tell it to fade between 0 and 1:
http://jsfiddle.net/hWTT6/6/
Notice that since I am telling it to fade to 0 or 1 everything works. A similar thing could be done to replace slideUp and slideDown using animate.

Categories

Resources