Need help with simple jQuery animation

I’m fairly new to jQuery (1.4.4) but finding it to be an incredible library of tools.

I recently scrapped my old image swapping JavaScripts for some new stuff I wrote for jQuery. It’s all working in jQuery the way it was working before without jQuery. So far so good.

Now I’m fiddling around with adding some jQuery animation effects and find the experience both disappointing and frustrating. I’m hoping it’s just me.

So I have images with an indexed id, like this…


<img id="m-0" src="/normal_0.jpg" />
<img id="m-1" src="/normal_1.jpg" />
etc.

With the following jQuery, I simply swap out the image (“m-0”) on mouseover to an image called “over_0.jpg” by changing the url in “src” for image element id “m-0”.

I’ve greatly simplified the code below for the purposes of this thread. The real code is doing image pre-loading, binding multiple elements, filling an array with all the URL’s for the hover images, etc.


$(document).ready(function() {
   var over; var out;
   $('img[id|="m"]').each(function (i) {
       $(this).hover(over, out);
       // *snipped* code in here filling various arrays with URL's
       // *snipped* code here doing some image pre-loading
   });

        function over(event) { // mouseenter
		$(this).attr("src", '/over_'+$(this).attr('id').replace(/m-/, "")+'.jpg');
	};
	function out(event) { // mouseout
		$(this).attr("src",'/normal_'+$(this).attr('id').replace(/m-/, "")+'.jpg');
	};
});

Ok, so the code above is working for me… swapping images.

The issue or question now is how can I apply a simple fadein or fadeout on the in/out events? I’ve been experimenting today and no matter what I do, I get the image swap and then an animation… or vice versa. It looks ugly since the background shows through… I just want to fade from one image to the next instead of a quick snap from one to the other.

Most of the plugins I’ve found seem to be overkill for this. Or they require two separate image elements… I just want to do it each image with my single img element.

If I can’t do it with a few simple lines, I’m going to live with it.

Thank-you for any suggestions or thoughts.

You’ll have to go with the multiple image solution, where you place one image directly over the other image, and then fade out (or in) the top image.

Oh good, they’re improved on that.

I just realised that your fadeOut is causing the image to be removed from the page. Once the image has completely faded out, it is removed from the visual flowe of your page. Due to that, the mouseleave event will trigger the next time the mouse moves, quickly followed by the mouseenter event again when the mouse moves over the image that’s fading back in.

The .fadeOut() method animates the opacity of the matched elements. Once the opacity reaches 0, the display style property is set to none, so the element no longer affects the layout of the page.

One simple solution is to not use fadeOut, because that completely removes the image, and to instead animate the opacity so that the image remains, but not seen.


$(this).animate({opacity: 0}, 1000);
...
$(this).animate({opacity: 1}, 1000);

And if you want to be able to interrupt the fading out, so that you can move the mouse out part-way through and it immediately fades back in:


$(this).stop().animate({opacity: 0}, 1000);
...
$(this).stop().animate({opacity: 1}, 1000);

I was afraid that would be the only solution.

Thank-you for confirming it.

I did some experimenting with this. I put a div inside of a div so one image is exactly over the other. The code below fades out/in the top image as the mouse hovers.


$(document).ready(function() {
   var over; var out;
   $('img[id|="m"]').each(function (i) {
       $(this).hover(over, out);
       // *snipped* code
   });

        function over(event) { // mouseenter
		$(this).fadeOut(1000);
	};
	function out(event) { // mouseout
		$(this).fadeIn(1000);
	};
});

Now the problem is that if I leave the mouse on top of the element and move it a little, the animation continues to cycle again!

According to jQuery docs the hover() function is only activated when the mouse enters the element and again when the mouse leaves the element. It says nothing about functions firing off when the mouse stays inside an element and just moves a little.

This is much more of a “curious, have you ever heard of this” type of question rather than a “I’m desperate to solve this” type of question. Thank-you.

This may help to clear things up for you - mouseenter()

It doesn’t. :confused:

[I].mouseenter( handler(eventObject) )

Description: Bind an event handler to be fired when the mouse enters an element, or trigger that handler on an element.[/I]

I’m a total jQuery newbie but the observed behavior seems very odd.

Even in the example at the bottom of that page, I can simply wiggle the mouse while it remains totally inside the left-hand yellow box and the counter increments as if I moved it out and came back in… it just doesn’t seem right and I don’t see where that’s explained.

That left example shows you the mouseover event, which is what hover uses. That is a demonstration of the problem.

The right example shows you the mouseenter event, which solves the problem.

DoH!

Didn’t realize mouseover() and thereby hover() had such a weird issue… it’s still not clear after reading the page three times… then again, I’m doing several things at once. :stuck_out_tongue:

THANK-YOU!

Wait a second… this is what it says on the hover() page…

http://api.jquery.com/hover/

The .hover() method binds handlers for both mouseenter and mouseleave events. We can use it to simply apply behavior to an element during the time the mouse is within the element.

So now I’m really confused. Why am I seeing this “mouse[B]over/B” problem when using “hover()”, if “hover()” binds “mouse[B]enter/B”?