...

View Full Version : jQuery super-custom easing menu :)



t1mmie
12-30-2009, 01:42 PM
Hey all. I'll be quite amazed if anyone can help me with this one. I've been scouring the internet trying to find a tutorial on this, but no such luck!!

I'm putting together my own little side navigation and I have an affect in my mind that I want to achieve and I'm sort of half-way there.

I've thrown together a demo, here (http://www.webhero.co.uk/help/) of what I've made so far.

I basically want the background to slide up and down depending on what menu the mouse hovers on to, with an easing (or bouncing) effect when you move over each one. I want the bouncing thing to go both ways, so that if the background is at the bottom and you hover over a link above, the background moves a little past the final result and then back -- so wherever it moves, it bounces or eases a little into place.

Another thing to consider is that whatever page the user is on, the little bar will start off and go back to there - so in the demo we're presuming the user is on the 'web design' page.

(You'll need to see the demo by now to see what I mean :P)

As you can see, I've programmed this to work fine if you're moving your mouse top to bottom, but if you go from bottom to top - you'll see in the code that I'll need to put some conditional statements around the animations to test whereabouts the background currently is - and that's what I need help with really. Also if anyone has a few tips on how I can shorten down my javascript code here that would be awesome :)

Or, if anyone has a better way of achieving what I'm trying to altogether then I gratefully welcome anyone's thoughts.

It'll be easier to view the source but I'll include the html and JS here.



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >

<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript"></script>
<script src="js.js" type="text/javascript"></script>
<script src="bg.js" type="text/javascript"></script>
<script src="png.js" type="text/javascript"></script>

<style>
#side {
min-height:600px;
height:600px;
width:243px;
float:left;
background:url(sidebg.jpg) no-repeat #333333;
background-position:71px 9px;
}

#side li, #side ul {
list-style:none;
padding:0;
margin:0;
float:left;
}

#side a * {
display: none;
}
#side a, #side a .hover {
height:36px;
width:172px;
position:relative;
display:block;
background:url(side.png);
}

#side a.webdesign {
margin:10px 0 7px 71px;
width:172px;
background-position:0 0;
}
#side .highlight a.webdesign:hover, #side a.webdesign .hover {
background-position:-172px 0;
}
#side a.seo {
margin:5px 0 7px 71px;
width:172px;
background-position:0 -40px;
}
#side .highlight a.seo:hover, #side a.seo .hover {
background-position:-172px -40px;
}
#side a.blog {
margin:5px 0 7px 71px;
width:172px;
background-position:0 -80px;
}
#side .highlight a.blog:hover, #side a.blog .hover {
background-position:-172px -80px;
}
#side a.contact {
margin:5px 0 7px 71px;
width:172px;
background-position:0 -120px;
}
#side .highlight a.contact:hover, #side a.contact .hover {
background-position:-172px -120px;
}

</style>

</head>

<body>

<div id="side" style="background-position: 71px 9px">
<ul>
<li class="highlight"><a href="webdesign" class="webdesign"><span>news</span></a></li>
<li class="highlight"><a href="seo" class="seo"><span>faq</span></a></li>
<li class="highlight"><a href="blog" class="blog"><span>contact</span></a></li>
<li class="highlight"><a href="contact" class="contact"><span>contact</span></a></li>
</ul>

</div>

</body>


and the javascript (jquery)



$(document).ready(function(){

// Side //

//var currentpos = $('#side').backgroundPosition();

$("#side a.webdesign").hover(function () {
$('#side').stop(true, false)
$('#side').animate({backgroundPosition: "71px 4px"}, 350);
$('#side').animate({backgroundPosition: "71px 9px"}, 150);
},
function () {
$('#side').stop().animate({backgroundPosition: "71px 9px"}, 400);
});

$("#side a.seo").hover(function () {
$('#side').stop(true, false)
$('#side').animate({backgroundPosition: "71px 63px"}, 350);
$('#side').animate({backgroundPosition: "71px 58px"}, 150);
},
function () {
$('#side').stop().animate({backgroundPosition: "71px 9px"}, 400);
});

$("#side a.blog").hover(function () {
$('#side').stop(true, false)
$('#side').animate({backgroundPosition: "71px 110px"}, 350);
$('#side').animate({backgroundPosition: "71px 105px"}, 150);
},
function () {
$('#side').stop().animate({backgroundPosition: "71px 9px"}, 400);
});

$("#side a.contact").hover(function () {
$('#side').stop(true, false)
$('#side').animate({backgroundPosition: "71px 159px"}, 350);
$('#side').animate({backgroundPosition: "71px 154px"}, 150);
},
function () {
$('#side').stop().animate({backgroundPosition: "71px 9px"}, 400);
});



});


Thanks to you all in advance :)

tomws
12-30-2009, 05:19 PM
I like the effect. A more experienced jquery dev probably has a thousand better ways to do this, but this is the first thing that pops into my head.

In each hover, you could play with "tracking" the position of the highlight by adding/removing a class. Hard-coding would be fairly easy and allow for simple comparisons of the class names, but it wouldn't be very extensible.

I took some time and poked around with the class name status tracking idea and using the index() function for determining current and last hovered li elements. Here's a somewhat working modification:


$(document).ready(function(){

$("#side a.webdesign").hover(function () {
$(this).closest('li').addClass('hovered');
$('#side').stop(true, false)
var last_index = $('#side li').index($('li.last-hovered'));
var my_index = $('#side li').index($(this).closest('li'));
if (last_index < my_index )
{
//alert('coming from below; indexes: '+last_index+'|'+my_index);
$('#side').animate({backgroundPosition: "71px 9px"}, 350);
$('#side').animate({backgroundPosition: "71px 4px"}, 150);
}
else
{
//alert('coming from above; indexes: '+last_index+'|'+my_index);
$('#side').animate({backgroundPosition: "71px 4px"}, 350);
$('#side').animate({backgroundPosition: "71px 9px"}, 150);
}
$('#side li.last-hovered').removeClass('last-hovered');
},
function () {
$(this).closest('li').removeClass('hovered');
$(this).closest('li').addClass('last-hovered');
$('#side').stop().animate({backgroundPosition: "71px 9px"}, 400);
});

$("#side a.seo").hover(function () {
$(this).closest('li').addClass('hovered');
$('#side').stop(true, false)
var last_index = $('#side li').index($('li.last-hovered'));
var my_index = $('#side li').index($(this).closest('li'));
if (last_index < my_index )
{
//alert('coming from below; indexes: '+last_index+'|'+my_index);
$('#side').animate({backgroundPosition: "71px 63px"}, 350);
$('#side').animate({backgroundPosition: "71px 58px"}, 150);
}
else
{
//alert('coming from above; indexes: '+last_index+'|'+my_index);
$('#side').animate({backgroundPosition: "71px 58px"}, 350);
$('#side').animate({backgroundPosition: "71px 63px"}, 150);
}
$('#side li.last-hovered').removeClass('last-hovered');
},
function () {
$(this).closest('li').removeClass('hovered');
$(this).closest('li').addClass('last-hovered');
$('#side').stop().animate({backgroundPosition: "71px 9px"}, 400);
});

$("#side a.blog").hover(function () {
$(this).closest('li').addClass('hovered');
$('#side').stop(true, false)
var last_index = $('#side li').index($('li.last-hovered'));
var my_index = $('#side li').index($(this).closest('li'));
if (last_index < my_index )
{
//alert('coming from below; indexes: '+last_index+'|'+my_index);
$('#side').animate({backgroundPosition: "71px 110px"}, 350);
$('#side').animate({backgroundPosition: "71px 105px"}, 150);
}
else
{
//alert('coming from above; indexes: '+last_index+'|'+my_index);
$('#side').animate({backgroundPosition: "71px 105px"}, 350);
$('#side').animate({backgroundPosition: "71px 110px"}, 150);
}
$('#side li.last-hovered').removeClass('last-hovered');
},
function () {
$(this).closest('li').removeClass('hovered');
$(this).closest('li').addClass('last-hovered');
$('#side').stop().animate({backgroundPosition: "71px 9px"}, 400);
});

$("#side a.contact").hover(function () {
$(this).closest('li').addClass('hovered');
$('#side').stop(true, false)
var last_index = $('#side li').index($('li.last-hovered'));
var my_index = $('#side li').index($(this).closest('li'));
if (last_index < my_index )
{
//alert('coming from below; indexes: '+last_index+'|'+my_index);
$('#side').animate({backgroundPosition: "71px 159px"}, 350);
$('#side').animate({backgroundPosition: "71px 154px"}, 150);
}
else
{
//alert('coming from above; indexes: '+last_index+'|'+my_index);
$('#side').animate({backgroundPosition: "71px 154px"}, 350);
$('#side').animate({backgroundPosition: "71px 159px"}, 150);
}
$('#side li.last-hovered').removeClass('last-hovered');
},
function () {
$(this).closest('li').removeClass('hovered');
$(this).closest('li').addClass('last-hovered');
$('#side').stop().animate({backgroundPosition: "71px 9px"}, 400);
});

});

Most of that can be moved out into a common function or two, of course, but copy/paste is a lot easier for quick hacking.

I think it works, but it's still not quite right. When the mouse leaves the hover areas (the links), the last-hovered status sticks to the last hovered anchor, but the highlight goes to the current page's link. The modification needs to set the last-hovered tracker to that same place, which should be easy enough with a little reorganization.

Also, the anchors don't fill up the li containers. That means it's possible to confuse the hover status tracker by simply moving between the links. That also should be easy enough to fix with a little html/css voodoo.

Anyway, even with those problems, maybe that will give at least one (sloppy) idea of how to solve the problem.

t1mmie
12-31-2009, 09:16 PM
Thanks for your reply dude. Sorry I didn't get back here sooner but someone beat you to it and actually managed to fix this using the 'easing' plug-in by simply adding:


.animate({backgroundPosition: "71px 53px"}, 500, 'easeOutBack');

Which was far too easy for my liking!!!! Nonetheless...

I do however have another issue..! :D As you can see here -http://bit.ly/7q6pBI in my side menu, when one of those pages are selected, I want the background bar to slide back to the page that is currently selected.

So if you're on the web-design page and hover over the 'seo' link, the background will move, but then on mouseout - the background snaps back to the original place rather than easing back. This is because I'm adding and removing a class each time a link is hovered over, which forces it back to the selected page.

I want to be able to add 'easeoutback' to the mouseout function basically... but other than this, I can't find another way of doing so :\

My code is as follows:

CSS - which works as it should..


#side {
min-height:600px;
height:600px;
width:243px;
float:left;
background:url(../images/sidebg.jpg) no-repeat;
background-position:<?php echo $side; ?>;
}
.sidebg {
background-position:<?php echo $side; ?> !important;
}


jQuery - code below is replicated for each button..



$("#side a.webdesign").hover(function () {
$('#side').removeClass('sidebg');
$(this).stop().fadeTo(350, 1);
$('#side').stop(true, false)
.animate({backgroundPosition: "71px 9px"}, 500, 'easeOutBack');
},
function () {
$(this).stop().fadeTo(250, 0.5);
$('#side').addClass('sidebg').fadeIn();
});


Should be all you need.. Thanks :)



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum