Question

I am trying to create a hover over action which brings in a coloured image and also once the hover is removed it fades back to its original image.

Currently it fades out the image to nothing and then fades the new one in. This will then stay in place regardless of whether i hover off or no.

//Loop through the images and print them to the page
   for (var i=0; i < totalBoxes; i++){
    $.ajax({
     url: "random.php?no=",
     cache: false,
     success: function(html) {
      // following line I originally suggested, but let's make it better...
      //$('#bg').append(html).fadeIn('slow');
      // also note the fine difference between append and appendTo.
      var $d = $(html).hide().appendTo('#bg').fadeIn('slow');
      $('img', $d).hover(function() {
       var largePath = $(this).attr("rel");
       $(this).fadeOut("slow", function() {
        $(this).attr({ src: largePath }).fadeIn("slow");
       });
      });
     }
    });
   }

Update:

Please take a look at this link:

http://www.yellostudio.co.uk/temp/index.php#

I am trying to get the images to cross fadein on rollover and out on fadeout...

Can anyone help, im so close and i have spent hours and hours trying to get my head around this...

Was it helpful?

Solution 7

OK thanks to you all for your help...i got somewhere...i am not totally happy as its slower than i originally intended because im loading two images in now as apposed to one...using the rel attribute made it alot quicker becaue i was loading the image only on hover...

But here is a solution thanks to you all...

          //Loop through the images and print them to the page
        for (var i=0; i < totalBoxes; i++){
            $.ajax({
                url: "random.php?no=",
                cache: false,
                success: function(html) {

                    var $d = $(html).hide().appendTo('#bg').fadeIn('slow');
                    $('#colour img').css("opacity", 0);
                    $('img', $d).hover(function() { 
                        $(this).stop().fadeTo(700, 1);
                    },function() {
                        $(this).stop().fadeTo(700, 0);
                    });

                }
            });
        }

and my php prints...

<div class="pf-box">
    <a href="#">
    <div class="black"><img src="'.$image_folder.'/'.$image_name.'.jpg" alt="'.$image_name.'" border="0" /></div>
    <div class="colour"><img src="'.$image_folder.'/'.$image_name.'-c.jpg" alt="'.$image_name.'" border="0" /></div>
    </a>
  </div>

OTHER TIPS

hover() takes two function parameters, one for mouseover and the other for mouseout. You've only supplied the first. You'll need to supply the second to undo the image swapping on mouseout.

If you want the fadeOut and fadeIn to be concurrent, don't put the fadeIn in the callback of the fadeOut. Just make them separate statements:

$(this).fadeOut("slow");
$(this).attr({ src: largePath }).fadeIn("slow");

The way you have it, the fadeIn doesn't start until the fadeOut is done. This way, they'll both start and finish at the same time.

I think you need to store the original image path (which is what you want to fade back to on hover out, right), then restore it on the hover out.

var $d = $(html).hide().appendTo('#bg').fadeIn('slow');
$('img', $d).hover(function() {
    var largePath = $(this).attr("rel");
    $(this).data('orig', $(this).attr('src') );
    $(this).fadeOut("slow", function() {
         $(this).attr({ src: largePath }).fadeIn("slow");
     });
},function() {
    var origPath = $(this).data('orig');
    $(this).fadeOut("slow", function() {
         $(this).attr({ src: origPath }).fadeIn("slow");
     });
});

Assuming that the "bright" image is used as the src attribute and you use opacity to achieve the effect.

var $d = $(html).hide().appendTo('#bg');
$('img',$d).css('opacity',0.33);
           .hover( function() {
               $(this).fadeTo('slow',1.0);
            }, function() {
               $(this).fadeTo('slow',0.33);
            });

Might I suggest: http://colorpowered.com/blend/

It will do what you are looking to do.


Edit: Okay, well, for one, I would definitely change the ajax part of your code to have it return all your images via json (even better I would do it on the back-end, but, I'm not sure how your site is setup). Anyways, it seems like you are fading out your other image unnecessarily. Simply place the color image above the other image with absolute positioning. Maybe your code could look something like this:

Javascript:

$.ajaxSetup({cache:false});
$('.hoverImg').live('mouseover',function() {
   $hovered = $(this);
   var colorPath = $hovered.attr("rel");
   var rndId = Math.floor(Math.random()*100000);
   var $colorImg = $('<img />');
   $colorImg
       .hide()
       .addClass("fader")
       .attr('src',colorPath)
       .attr('id','img_'+rndId)
       .css({position:'absolute',zIndex:10});
   $hovered.css({zIndex:9}).data('overImgId',rndId).before($colorImg);
   $('#img_'+rndId).stop().fadeIn("slow");
});
$('.hoverImg').live('mouseout',function() {
    var rndId = $(this).data('overImgId')
    $('#img_'+rndId).stop().fadeOut("slow");
});
$.getJSON('random.php',{numBoxes:totalBoxes},function(json) {
    if(json.length > 0) {
        $.each(json,function(i,val) {
            $(val).hide().appendTo('#bg').find('img').addClass('hoverImg');
        });
    }
});

PHP:

<?php //random.php (really simplified, probably)
if(isset($_GET['numBoxes']) && !empty($_GET['numBoxes'])) {
    /*
        Get all the html stuff you need into an array...
        Could look something like:
        $imgs = array(
            '<div><img src="foo.jpg" rel="color_foo.jpg" /></div>',
            '<div><img src="bar.jpg" rel="color_bar.jpg" /></div>'
        );
    */
    echo json_encode($imgs);
}

That should basically work. There might be some typos and stuff in there but, from what I can tell, it should work. Of course, depending on your scenario, you may need to tweak/alter some of this.

Good luck on your project!

IMPORTANT EDIT: I forgot to add a key part to the PHP code. I added the "rel" attrs to the <img> tags.

You could do this using some additional code. Position the fade-in image on top of the fade-out image, with opacity set to 0. Add the hover code to the fade-in image (it's on top, so it gets the events).

$('#top-image').hover(function() {
$(this).stop().fadeTo(1000, 1);
$('#bottom-image').stop().fadeTo(1000, 0);
},
function() {
$(this).stop().fadeTo(1000, 0);
$('#bottom-image').stop().fadeTo(1000, 1);
});

Both images fade in and out, and with the use of the stop() function, mousing in and out rapidly won't lead to a series of repeated animations.

If you want to do a cross-fade you need two images, one that is fading in, and one that is fading out concurrently. Take a look at a page I did with this effect. The plugin I wrote is right in the page source so you can take a look at it. The two images will need to have position: absolute; so that as they cross-fade they can occupy the same area of the page.

And like No Surprises said, you are only supplying a callback to hover for the mouse hover, and not the mouse un-hover which is where you would cross-fade back to the original.

This code may work, remember the absolute positioning in your CSS, and you may want to add a CSS class to the backImg, and the images must be in a discrete parent element that the hover event is subscribed on:

for (var i=0; i < totalBoxes; i++){
    $.ajax({
        url: "random.php?no=",
        cache: false,
        success: function(html) {
            $(html)
                .hide()
                .appendTo('#bg')
                .fadeIn('slow')
                .children('img').each(function() {
                    var img = $(this);
                    var largePath = img.attr("rel");
                    var backImg = $("<img src='" + largePath + "'/>");
                    img.after(backImg);

                    img.parent().hover(
                        function() { // over
                            backImg.stop().fadeIn("slow");
                            img.stop().fadeOut("slow");
                        },
                        function() { // out
                            backImg.stop().fadeOut("slow");
                            img.stop().fadeIn("slow");
                        }
                    );
                });
        }
    });
}

I spotted a problem here...

var backImg = $("<img src='" + largePath + "'/>");

This isn't a valid selector. Try this instead:

var backImg = $('img[src="' + largePath + '"]');

You don't want to use the <> in your selector, and the attribute selector syntax should look like this: [attr="value"]
You should note that I reversed the use of ' and " in my code - that's just how I do it, it's syntactically identical. There's nothing wrong with your choice of quotes.

In your stylesheet add:

.colour {
  display:none;
}

Then make your success function read:

var $d = $(html).hide().appendTo('#bg').fadeIn('slow');
$('.pf-box', $d).hover(function() {
  $('.colour', $(this)).fadeIn("slow");      
},function() {
  $('.colour', $(this)).fadeOut("slow");      
});

UPDATE

To solve the slow loading problem you'll need to have your PHP return an object of all images like so (let's say it's called images.php -- put the code below inside of <?php ?>) (you'd want to use json_encode() but he was on an older version of PHP):

header('Content-type: application/json');
echo '{
  {'black' : 'url', 'colour' : 'url'},
  {'black' : 'url2', 'colour' : 'url2'}
}';

Then in javascript you want:

//generate all the boxes
$.get('images.php',function(data){
  for (var i=0; i < totalBoxes; i++){
      var randomImage = data[Math.floor(Math.random() * data.length)];
      $('<div class="pf-box"><img class="black" src="' + randomImage['black'] + '" /><img class="colour" src="' + randomImage['colour'] + '" /></div>').hide().appendTo('#bg').fadeIn('slow').filter('.colour').css("opacity", 0);
  }
 },'json');

 //add the hover behavior to all the elements
 $('.pf-box').hover(function() {
   $('.colour',$(this)).stop().fadeTo(700, 1);
 },function() {
   $('.colour',$(this)).stop().fadeTo(700, 0);
 });

This code should work...but I haven't tested it. There might be typos. But this is the gist of it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top