views:

650

answers:

8

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...

+1  A: 

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.

No Surprises
Applying two concurrent animations on one element will not provide a cross-fade effect. Your code will start to fade out but not all the way, then instantly change the image while it's fading out and fade back.
joshperry
Hi no Suprises, thanks for your help....I added the code and it seems to be working however i try and get the fade out bit working and i always get a syntax error and a blank screen...could you shed some light on this? Thanks again
Andy
Here is a link http://www.yellostudio.co.uk/temp/index.php#
Andy
Your right joshperry it doesnt give a cross fade anim
Andy
Oh, sorry. joshperry is right: that only works if you have two images and they're positioned absolutely on top of each other.
No Surprises
Does it make any difference that i am calling it via "rel"?
Andy
A: 

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");
      }
     );
    });
  }
 });
}
joshperry
could you give me an idea on how to ammend my code to encorporate a mouse out? Its using the rel attribute to pull in the new image.
Andy
joshperry, thanks for your help on this...i really have spent hours...i have uploaded the code so you can see whats happening...unfortunately it is not working.
Andy
I've added code that may work for you, but I'd still recommend using the more generalized blend plugin in KyleFarris' answer.
joshperry
joshperry
I have updated it now and its getting there, just the cross fade bit...and its flashing at the start of the hover instead of fading in over the top...thanks josh!
Andy
fair do's! I dont mind paying for a solution...im that fed up with it now
Andy
if you want a cross-fade you HAVE to have two images, one to fadein and one to fadeout, your code is back to attempting to use one image again, see my comments on @No Surprises answer for why this won't work. If you make html that comes back from your server have each img wrapped in a DIV my code my work for you. Really though, just download the blend plugin, it's free.
joshperry
Thanks josh, i know im clutching at straws here....its just so frustrating because ive spent days and days figuring getting this far and then i found this forum. you have been a tremendous help and ill try and figure it out based on your comments...i just thought the whole "rel" attribute was really cool way of doing it.Thanks again
Andy
Nothing wrong with the rel technique as long as you generate a second image using that url in your script (like mine does). Again, if you modify your ajax response to wrap each img in a div my code may work for you.
joshperry
If i get it to print this...<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>
Andy
+1  A: 

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.

KyleFarris
Thanks for this, it looks really useful but i was hoping just to ammend my code as i know i am nearly there... :@) i hope!
Andy
wow that is totally different to what i have. I'll try it and see how i get on. I dont hvae any experience in json
Andy
@Andy: It's definitely worth learning. ;)
KyleFarris
Is the jquery blend plugin yours? I just sent you an email.
Andy
Id like to pay you do add your solution as although i hvae it working its very slow and the fade in effect i was hoping for just work. The fade was working perfectly when i was using the rel attribute to reference the other image but i couldnt get the crossfade happening....
Andy
No, I didn't make the blend plugin that I linked to. It's a pretty nice one though. I won't be needing any sort of payment for any solution I give you on this site. Is what I provided above not working for you?
KyleFarris
NO it wasnt but i could try adding it again now quickly with your ammend?
Andy
Didnt work sorry...i left the code there though if you had time to check it was in place right:http://www.yellostudio.co.uk/temp/index.php#
Andy
A: 

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.

Frank DeRosa
Would you be interested in a payment to get this thing working for me?
Andy
I amm not sure how to add your above code into what i have already!
Andy
This is just example code, I just wrote it off the cuff. Feel free to contact me if you're still stuck...
Frank DeRosa
just trying one other solution from anotehr user...so lost in this all now :)
Andy
+1  A: 

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);
            });
tvanfosson
Hey thanks tvanfosson, the code you suggested i have just tested and its working but there is a weird flash at the start of the hover and it doesn't cross fade, if you have time to check the link i would appreciate it...
Andy
I didn't think about this but you need to wait until the fadeOut completes before replacing the src attribute. Otherwise you end up with the new image at full opacity (the flash) before the fadeOut completes. Do this by moving the change into the fadeOut callback. Also, have you thought about simply adjusting the opacity between 50% and 100% on hover using the same "bright" image instead of switching between light and dark images. This might be the "cross fade" effect that you're looking for.
tvanfosson
Would you accept payment to get this working for me?
Andy
A: 

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.

Aaron
Thanks aaron, i tried your method and it didnt work unfortunately. I resorted to my answer below...although its really clunky now...not happty with it :"(
Andy
ok this looks promising, does it loop through the array then regardless of how many are returned? So if i did a resize function it would loop through the same array and add more?
Andy
Ive given it a go but it doesnt define the source...i checked it in firebughttp://www.yellostudio.co.uk/temp/indexV2.php
Andy
You have a parse error on your images.php page: "syntax error, unexpected ':' in /home/sites/yellostudio.co.uk/public_html/temp/images.php on line 3
Aaron
<?php { "images" : { "black" : "images/random/1.jpg", "colour" : "images/random/1-c.jpg" }, { "black" : "images/random/2.jpg", "colour" : "images/random/2-c.jpg" }}?>
Andy
i just pasted what you put on this post and changed the URLs was that wrong? Thanks again aaron. You're helping me out no end!
Andy
You've got to echo that...I'll update my post with the exact php
Aaron
sorry mate! Im being stupid!
Andy
still nothing:http://www.yellostudio.co.uk/temp/indexV2.php Parse error: syntax error, unexpected ':', expecting ')' in /home/sites/yellostudio.co.uk/public_html/temp/images.php on line 6
Andy
check your images.php code carefully...that error makes no sense in light of what I put up there
Aaron
Here is an exact copy...<?php header('Content-type: application/json');echo json_encode(array( array( "black" : "images/random/1.jpg", "colour" : "images/random/1-c.jpg" ), array( "black" : "images/random/2.jpg", "colour" : "images/random/2-c.jpg" )));?>
Andy
take out the ":" between the key and value and use "=>" instead...just like I have in my post
Aaron
I see your error -- looks like you're running an older version of PHP
Aaron
Sorry didnt notice that bit had changed....still no go sorry!http://www.yellostudio.co.uk/temp/indexV2.php
Andy
just updated it to php5 using .htaccess
Andy
SetEnv DEFAULT_PHP_VERSION 5
Andy
you need php 5.2 for json_encode() http://www.php.net/manual/en/function.json-encode.php -- but I've updated my post again with manually-created JSON -- try that
Aaron
I cant believe your helping me as much as you are...thanks so much...but...<?php header('Content-type: application/json');echo '{ {'black' : 'images/random/1.jpg', 'colour' : 'images/random/1-c.jpg'}, {'black' : 'images/random/2.jpg'', 'colour' : 'images/random/2-c.jpg'}}';?>
Andy
looks like you fixed it by moving to php5 -- well, you're really close now. For some reason jQuery's not interpreting it as a JSON array
Aaron
try using $.getJSON instead of $.get (and get rid of the last parameter - json -- from your get call)
Aaron
mmm i dont see any images, but im guessing thats because of what you just mentioned. I hvae no knowledge of json sorry!
Andy
just completed what you said
Andy
Well...you're really close. Sorry I've got to run at this point but I'll check in later. Your PHP is good now. You just need to get the javascript to parse the JSON correctly.
Aaron
ok ill see what i can acheive...thank you so much for your efforts...
Andy
You know what...I think you may need to send it a JSON object, not an array. In your PHP change json_encode(yourarrayhere) call to look like this json_encode(yourarrayhere, JSON_FORCE_OBJECT)
Aaron
get rid of display:none on .colour elements
Aaron
get rid of visibility:hidden -- and check out the hover portion of the javascript in my answer. I've edited it and it now works a bit differently. Copy it all over.
Aaron
Your twirling loading background image is also causing a lot of cpu usage (a steady 100% on an older 2.4 ghz Sempron machine I have) -- you probably want to remove it once the page is done loading.
Aaron
A: 

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.

Frank DeRosa
THanks for your input, i cannot find any reference to backImg
Andy
A: 

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>
Andy
What part do you find slow? The initial load or the hovering?
Aaron
loading in is slow because im loading two images...before i was trying to load one then use the rel attribute to load the second only when it was hovered which gave a much smoother fade in one after the other when you first load the page.
Andy
If you want the initial fade in to be quick then just change fadeTo(700,1) to something faster like fadeTo(100,1)
Aaron
no sorry i mean when it appends the images to the page i have it fading in...so it loops through pulls and image from random then appends to the page using fade. Before it was really swift but now its clunky because im bring two images from the random page as apposed to referencing the rel attribute on hover to swap the image...
Andy
ah, so it's the initial pageload that you're worried about -- for that I would not iterate over your ajax call. That's way too much overhead. Call your ajax once and have it return an array of all possible images then repeatedly pull random images from that array in javascript.
Aaron
Thanks aaron for talking to me about this...ill tell you why i did it this way because when i resize the window its going to run the javascript function and add more boxes if necessary based on the viewport height and width...therefor if i had an array it would already be predefined which would mean when resizing i would have a blank space.
Andy
Check my answer again for an update -- I just posted a bunch of code. You can get the dynamic behavior you want without hitting the server on every call. Just pull down the array of possible images once, then generate as much html as you like.
Aaron
this is cool however its not pulling in the source...
Andy
i checked it in firebug yellostudio.co.uk/temp/indexV2.php
Andy