.fadeIn() / fadeOut() on mousemove - javascript

I got a problem with smooth fadeIn and fadeOut in mousemove... I am doing some calculations about what is under top element, and based on those calculations I would like to fadeIn() or fadeOut() tooltip. The problem is that when moving a mouse, events are being shoot like every few milliseconds.
The sitiuation looks like this:
I move the mouse, tooltip is hidden. Suddenly mouse pointer is on top of element that should trigger fadeIn(), but this element is not the triggerer, because it is behind of some other element. So I need to shoot fadeIn() from mousemove. But, when I shoot it, every few milliseconds, it doesn't work, or works million times. But generally, it does not... animation simply stucks as long as I move mouse, because fadeIn() is being called all over again. I am really tired of this, tried to fix it for like 5 hours and nothing.
I've tried:
.stop() before fadeIn() / fadeOut() in different configurations... but the only visible effect I got was that it looked like show(), because stop(true,true) simply deletes the queue and leads to the end of last animation. So, wow! It is show... how... eghn... great :/
Using :visibe selector to fadeOut() and :not(:visible) to fadeIn() ... well.. that of course did not change much, an with stop() it was just leaving semitransparent tooltip
Using rel attribute to define that the fadeOut() was already shoot and should not be shoot anymore... even worse idea, because it simply did not come back after total fadeOut()
To get some reset and thing, but I can't rest when I don't have this problem resolved - it is sooo annoying!
I wonder if anybody reads this anyway... I wouldn't.
So HOW to limit fadeOut(), fadeIn() events to one each time so it would smoothly fadeIn and fadeOut even from middle of animation when event is triggered by mousemove?
I will probably get -1000 for this question... doooh.

I'd suggest you use css for this instead. You lose a bit of compatibility (Most notably older IE's), but it's simpler and will run a lot smoother.
E.g. define opacity in a :hover pseudo class, and then define a transition property with a timing of your choice.
Edit:
Using css in this case has no use because as I said, the event is not trigered by top most layer... stop(true,true) works exactly te same as show() because it is called every few milliseconds, and once is enough to stop fade effect.
In that case, set/unset a class on the fading-element inside your event handler. Let css do the work for you.
E.g.:
<style>
#tooltip { opacity:0 ; transition:opacity 1s linear }
#tooltip.enabled { opacity:1 }
</style>
<div class="has-tooltip">Foo</div>
<div id="tooltip">Tooltip</div>
<script>
$(".has-tooltip")
.on("mouseenter", function() { $("#tooltip").addClass("enabled") })
.on("mouseleave", function() { $("#tooltip").removeClass("enabled") })
</script>

You can try to unbind events before FadeIn/fadeOut and bind again after animation is complete (in complete function).

try this, call this function on mouse move
TIMER='';
function onmove()
{
if(TIMER)
clearTimeout(TIMER);
else
TIMER = setTimeout(function(){
// use yor code here eg. $('whteverID').fadeIn();
},10)
}

Related

Interval doesn't clear immediately after repeating for a while

I have a bouncing arrow on my website that I created with Jquery and setInterval, like this:
bouncing = setInterval(function() {
$("div").animate({
top:"30px"
},100,"easeInCubic",function() {
$("div").animate({
top:"0px"
},100,"easeOutCubic");
});
console.log("bounced");
},200);
You can see this in place in a codepen here: http://codepen.io/mcheah/pen/wMmowr
I made it run faster than i needed because its easier to see the issues quicker. My issue is that after leaving the interval running for a few seconds, you'll notice that instead of bouncing back up or down immediately, the bouncing element will stop for half a second and then just hang there, before beginning again. If you leave it running even longer (20 seconds) and then clear the interval, you'll notice that it takes a few seconds to stop bouncing.
My questions are these:
Why does the bouncing go out of sync occasionally?
Why does the clear interval take a while to clear if it's been repeating for a while?
Is there a better way to have a bouncing arrow? Are CSS transitions more reliable?
Thanks for your help!
Your are trying to perfectly coordinate a setInterval() timer and two jQuery animations such that the two come out perfectly coordinated. This is asking for trouble and the two may drift apart over time so it is considered a poor design pattern.
If, instead, you just use the completion of the second animation to restart the first and make your repeat like that, then you have perfect coordination every time.
You can see that here in another version of your codepen: http://codepen.io/anon/pen/NxYeyd
function run() {
var self = $("div");
if (self.data("stop")) return;
self.animate({top:"30px"},100, "easeInCubic")
.animate({top:"0px"}, 100, "easeOutCubic", run);
}
run();
$("div").click(function() {
// toggle animation
var self = $(this);
// invert setting to start/stop
self.data("stop", !self.data("stop"));
run();
console.log("toggled bouncing");
});
It's not a good idea to mix animate() with timers this way. There's NO chance you can synchronize something like this. And there's no need to. You can simply append a function into the animation queue, look here: https://stackoverflow.com/a/11764283/3227403
What animate() does is put an animation request into a job queue which will be processed later, when the right time comes. When you break the interval the stuff that accumulated in the queue will still be processed. There's a method to clear the queue and stop all animation immediately.
The JQuery animation functions actually manipulate CSS, and there is nothing beyond it in HTML. Another option would be using a canvas, but it is a completely different approach and I wouldn't recommend it. With JQuery's animation your already at the best choice.
This is a simple solution to your problem:
function bounce()
{
$("div")
.animate({
top: "30px"
}, 100, "easeInCubic")
.animate({
top: "0px"
}, 100, "easeOutCubic", bounce); // this loops the animation
}
Start bouncing on page load with:
$(bounce);
Stop bouncing on click with:
$("div").click(function() {
$("div").stop().clearQueue().css({ top: "0px" });
// you want to reset the style because it can stop midway
});
EDIT: there were some inaccuracies I corrected now. The running example is on codepen now.
If you want to use javascript for animation you can use something better like the greensock tween library
http://greensock.com/docs/#/HTML5/GSAP/TweenMax/to/
something like this:
var tween = TweenMax.to($("div"), 100, {y: "100px", yoyo: true, repeat: -1});
You could wrap your interval code with:
if(!$("div").is(":animated"))
This will initiate your animation only if your previous one is finished.
The reason why it was bouncing weird is that your animations are queued.
You can check how it works now:
http://codepen.io/luminaxster/pen/XKzLBg
I would recommend using the complete callback when the second animation ends instead and have variable to control a bounce recursive call in this version:
http://codepen.io/luminaxster/pen/qNVzLY

Make sure only one animation is being fired

I am running this animation on $(window).scroll() and it works fine for the most part.
$('#el').animate({ left: toMove }, 500);
The problem is if the user scrolls too fast, two animations will fire and the second animation will fire before the first one has moved far enough. How can I make sure there is only one animation at any given time and then the other animations will follow? I need the element to animate left FULLY any other animations run but I need them all to run. I tried using .queue() but couldn't find the right solution with it.
You could use the stop function like this to smooth things up:
$('#el').stop(true, false).animate({ left: toMove }, 500);
The stop function, when calling like that will clear the animation queue for any waiting animation, as well as stop the current animation if any.
Edit
If you want the animation to end before animating again you just need to call .stop(true, true) instead

Jquery mouseover & mouseout animation bug

I have a small mouseover and mouseout functionality i have to keep the mouseout function animate() instead of css() due to other reasons
the problem arises when i mouseover when the animation from opacity 1 to 0 is still going on like a quick mouseover mouseout like we do for testing.
i tried setTimeOut too so that the opacity is zeroed after required time.
both animate and setTimeOut are creating the same problem that after mouserover function updates the opacity to 1 the animate and setTimeOut are updating again to zero since they are still playing.
JSFIDDLE
Jquery Code:
$("#dp-ashish").on("mouseover",function(){
$("#dp-ashish").css("opacity","1");
});
$("#dp-ashish").on("mouseout",function(){
$("#dp-ashish").animate({"opacity":"0"},1000);
});
You might want to consider using either .stop(true, true) or .finish() (the latter only works in jQuery v1.9 and above):
$("#dp-ashish").on("mouseover",function(){
$("#dp-ashish").stop(true,true).animate({opacity:1},1000);
});
$("#dp-ashish").on("mouseout",function(){
$("#dp-ashish").stop(true,true).animate({opacity:0},1000);
});
or:
$("#dp-ashish").on("mouseover",function(){
$("#dp-ashish").finish().animate({opacity:1},1000);
});
$("#dp-ashish").on("mouseout",function(){
$("#dp-ashish").finish().animate({opacity:0},1000);
});
p/s: The opacity and its numerical integer value do not need to be wrapped in quotes. Opacity is a valid property without needing to be parsed as a string, and its accepted values are integers which do not need to be passed as a string, too.
Alternatively, you can toggle a CSS class and let CSS transitions handle the opacity change :)
http://jsfiddle.net/teddyrised/5Ekbf/4/

jQuery Hover mouseenter mouseleave

i´m trying to do a hover effect using this script:
function itemhover(){
$(".item").mouseenter(function(){
$(".mask").fadeIn();
})
$(".item").mouseleave(function(){
$(".mask").fadeOut();
})
}
The problem is that when I hover over any item it fades in the .mask of all, how can I point the function to just work on the item that is being hovered?
Also when I pass the mouse in and out on the item real quick, the fade effects goes crazy, is like it doesn´t stop, then it stop after a while, why is that?
thanks
It sounds like your .mask element is contained within your .item element. If that is the case, then you can use $(this) to "set the scope" of the item being hovered (this refers to the item being hovered).
function itemhover(){
$(".item").mouseenter(function(){
$(this).find(".mask").stop(true, true).fadeIn();
})
$(".item").mouseleave(function(){
$(this).find(".mask").stop(true, true).fadeOut();
})
}
Also, you might want to chain .stop(true, true) before your fade animation effect to stop any previously queued animations and to jump to the end of the last queued animation.
you can use the this statement
$(".mask",this).fadeIn();

jQuery - Fading animation on hover

I have a little jQuery animation which fades in a link when hovering an :
$(function() {
$('.delete').hide();
$('#photos img').hover(function() {
$(this).parents('li').children('.delete').fadeIn('fast');
}, function() {
$(this).parents('li').children('.delete').fadeOut('fast');
});
});
But if I quickly move my mouse in and out of the image, the new animation is always added to the queue and when I stop I can see the link pulsating for a while. I tried using .stop(true), but then sometimes the fade in effect doesn't work at all (or just up to some opacity value less than 1). What can I do?
Thanks, Eric
The best way is to use hoverIntent plugin. This deals with the issues above. It also adds a slight delay to the animation so if a user happens to quickly move the mouse over all the links you do not get an ugly animation flow of all the links.
One way to prevent such problems occuring is to use stop() in conjunction with fadeTo(), as in the snippet below:
$(function() {
$('.delete').fadeTo(0, 0);
$('#photos img').hover(function() {
$(this).parents('li').children('.delete').stop().fadeTo('fast', 1);
}, function() {
$(this).parents('li').children('.delete').stop().fadeTo('fast', 0);
});
});
Hope this solves your issue!

Categories