search check home clock-o tag tags chevron-left chevron-right chevron-up chevron-down twitter facebook github rss comment comments terminal code

[CSS][jQuery] Efektowne menu z tłami

[CSS][jQuery] Efektowne menu z tłami

W dzisiejszym artykule przedstawię sposób na zbudowanie bardzo efektownego menu przypominającego animacje Flash. Głównym zamierzeniem tego efektu jest posiadanie trzech obrazków jako tło pod każdą osobną pozycją menu, który to obrazek się zmienia zależnie od tego, które pozycja z menu zostanie wskazana.
Moim zdaniem taki efekt można skutecznie wykorzystać na stronach portfolio czy stronach studiów fotograficznych.

Najpierw należy stworzyć strukturę takiego menu. W tym przypadku menu będzie wyglądało w następujący sposób:

<div id="kontener">
<ul class="menu" id="menu">
<li class="bg1" style="background-position:0 0;">
      <a id="bg1" href="#">Miasto</a>
<ul class="podmenu1" style="background-position:0 0;">
<li><a href="#">Link 1</a></li>
<li><a href="#">Link 2</a></li>
<li><a href="#">Link 3</a></li>
</ul>
</li>
<li class="bg1" style="background-position:-266px 0px;">
         <a id="bg2" href="#">Wąż</a>
<ul class="podmenu2" style="background-position:-266px 0;">
<li><a href="#">Link 1</a></li>
<li><a href="#">Link 2</a></li>
<li><a href="#">Link 3</a></li>
</ul>
</li>
<li class="last bg1" style="background-position:-532px 0px;">
         <a id="bg3" href="#">Niebo</a>
<ul class="podmenu3" style="background-position:-266px 0;">
<li><a href="#">Link 1</a></li>
<li><a href="#">Link 2</a></li>
<li><a href="#">Link 3</a></li>
</ul>
</li>
</ul>
</div>

Dla uproszczenia wykorzystałem zagnieżdżone style CSS. To nie jest dobra praktyka webmasterska, ale musisz mi wybaczyć taki krok.

Kolejnym krokiem jest zdefiniowanie stylu CSS dla naszego menu:

#kontener {
    font-size: 15px;
    font-style: normal;
    font-weight: normal;
    text-transform: uppercase;
    letter-spacing: normal;
    line-height: 1.45em;
    position: relative;
    margin: 20px auto;
    height: 542px;
    width: 797px;
    background-position: 0 0;
    background-repeat: no-repeat;
    background-color: transparent;
}
ul.menu {
    list-style: none;
    width: 797px;
}
ul.menu > li {
    float: left;
    width: 265px;
    height: 542px;
    border-right: 1px solid #777;
    background-repeat: no-repeat;
    background-color: transparent;
}
ul.menu > li.last {
    border: none;
}
.bg1 {
    background-image: url(../images/1.jpg);
}
.bg2 {
    background-image: url(../images/2.jpg);
}
.bg3 {
    background-image: url(../images/3.jpg);
}
ul.menu > li > a {
    float: left;
    width: 265px;
    height: 50px;
    margin-top: 450px;
    text-align: center;
    line-height: 50px;
    color: #ddd;
    background-color: #333;
    letter-spacing: 1px;
    cursor: pointer;
    text-decoration: none;
    text-shadow: 0px 0px 1px #fff;
}
ul.menu > li ul {
    list-style: none;
    float: left;
    margin-top: -180px;
    width: 100%;
    height: 110px;
    padding-top: 20px;
    background-repeat: no-repeat;
    background-color: transparent;
}
ul.menu > li ul li {
    display: none;
}
ul.menu > li ul.podmenu1 {
    background-image: url(../images/bg1.png);
}
ul.menu > li ul.podmenu2 {
    background-image: url(../images/bg2.png);
}
ul.menu > li ul.podmenu3 {
    background-image: url(../images/bg3.png);
}
ul.menu > li ul li a {
    color: #fff;
    text-decoration: none;
    line-height: 30px;
    margin-left: 20px;
    text-shadow: 1px 1px 1px #444;
    font-size: 11px;
}
ul.menu > li ul.podmenu1 li {
    display: block;
}
ul.menu > li ul li a:hover {
    border-bottom: 1px dotted #fff;
}

Ostatnim krokiem jest stworzenie skryptu JavaScript, który będzie odpowiednio animował nasze menu.
Szczegóły tego kodu są opisane w komentarzach w kodzie.

$(function() {
	/* pozycja znacznika
<li> który jest obecnie pokazany */
	var stanObecny = 0;
 
	var stanZaladowany  = 0;
	for(var i = 1; i &lt;4; ++i)
		$('<img />').load(function(){
			++stanZaladowany;
			if(stanZaladowany == 3){
				$('#bg1,#bg2,#bg3').mouseover(function(e){
 
					var $this = $(this);
					/* jeśli najedziemy na pokazany znacznik to nic nie robi */
					if($this.parent().index() == stanObecny)
						return;
 
					/* obiektami najazdu są bg1 lub bg2 lub bg3, zależnie od tego który wskażemy kursorem */
					var obiektMenu = e.target.id;
 
					/*
					tutaj ustawiamy tło podmenu.
					Ustawiamy kierunek ruchu animacji zależnie od tego z której strony
					najedziemy kursorem.
					Jeśli najedziemy z lewej strony obrazka to animacja będzie
					szła od prawej do lewej, a jeśli z prawej strony najedziemy
					to animacja będzie szła od lewej do prawej
					 */
					if(obiektMenu == 'bg1' || stanObecny == 2)
						$('#menu .podmenu'+parseInt(stanObecny+1)).stop().animate({backgroundPosition:"(-266px 0)"},300,function(){
							$(this).find('li').hide();
						});
					else
						$('#menu .podmenu'+parseInt(stanObecny+1)).stop().animate({backgroundPosition:"(266px 0)"},300,function(){
							$(this).find('li').hide();
						});
 
					if(obiektMenu == 'bg1' || stanObecny == 2){
						/* animacja od lewej do prawej */
						$('#menu > li').animate({backgroundPosition:"(-800px 0)"},0).removeClass('bg1 bg2 bg3').addClass(obiektMenu);
						move(1,obiektMenu);
					}
					else{
						/* animacja od prawej do lewej */
						$('#menu > li').animate({backgroundPosition:"(800px 0)"},0).removeClass('bg1 bg2 bg3').addClass(obiektMenu);
						move(0,obiektMenu);
					}
 
					/*
					Część środkowa menu, też powinna ulec animacji, gdy będziemy przejeżdżać
					kursorem nad częścią środkową.
					Animacja ma być zależna od kierunku najazdu.
					To jest ważne w przypadku przechodzenia od pierwszego do ostatniego lelemntu menu
					lub na odwrót.
					 */
					if(stanObecny == 2 && obiektMenu == 'bg1'){
						$('#menu .podmenu'+parseInt(stanObecny)).stop().animate({backgroundPosition:"(-266px 0)"},300);
					}
					if(stanObecny == 0 && obiektMenu == 'bg3'){
						$('#menu .podmenu'+parseInt(stanObecny+2)).stop().animate({backgroundPosition:"(266px 0)"},300);
					}
 
					/* zmień obecny element */
					stanObecny = $this.parent().index();
 
					/* nakładanie tła dla podmenu */
 
					$('#menu .podmenu'+parseInt(stanObecny+1)).stop().animate({backgroundPosition:"(0 0)"},300,function(){
						$(this).find('li').fadeIn();
					});
				});
			}
		}).attr('src', 'images/'+i+'.jpg');
 
		 function move(dir,obiektMenu){
			  if(dir){
					$('#bg1').parent().stop().animate({backgroundPosition:"(0 0)"},200);
					$('#bg2').parent().stop().animate({backgroundPosition:"(-266px 0)"},300);
					$('#bg3').parent().stop().animate({backgroundPosition:"(-532px 0)"},400,function(){
						 $('#kontener').removeClass('bg1 bg2 bg3').addClass(obiektMenu);
					});
			  }
			  else{
					$('#bg1').parent().stop().animate({backgroundPosition:"(0 0)"},400,function(){
						 $('#kontener').removeClass('bg1 bg2 bg3').addClass(obiektMenu);
					});
					$('#bg2').parent().stop().animate({backgroundPosition:"(-266px 0)"},300);
					$('#bg3').parent().stop().animate({backgroundPosition:"(-532px 0)"},200);
			  }
		 }
	});
</li>

Należy pamiętać o tym, aby dodać do naszego pliku HTML bibliotekę jQuery oraz plugin jquery.bgpos. Dzięki temu nasz efekt zadziała tak jak tego chcemy.

To byłoby wszystko, jeśli chodzi o ten artykuł.
Działający przykład możesz zobaczyć pod tym linkiem: efektowne menu z przewijanymi tłami


Tak jak obiecałem, dorzucam spakowaną wersję demo tego efektu do pobrania: pobierz efektowne menu z tłami

  • jacek

    Dzięki za poradę demo się świetnie prezentuje , ale niestety mam dziwny problem. Najpierw zgodnie z tym co piszesz poskładałem stronę i nie działa, więc skopiowałem sobie demo poprzez opere, i FF do dwóch różnych folderów, porównałem i znowu nie działa. sprawdziłem oczywiście podlinkowane biblioteki style wszystko ok ale dalej problem strona całkowicie statyczna zatrzymuje się na pierwszej zakładce i nie działa animacja. Może gdzieś byś zuploadował spakowaną działającą stronę ?porównał bym sobie może bym doszedł gdzie tkwi błąd. Pozdrawiam

  • Myślę, że w przeciągu tygodnia, na Twoje życzenie, wrzucę spakowane demo z tego artykułu na stronę.

  • jacek

    Będę zobowiązany , pozdrawiam.

  • Marcin

    Witam,
    U mnie tez nie dziala, rowniez bede czekal na spakowany plik z dzialajaca strona.

  • zaktualizowałem wpis i plik demo jest gotowy do pobrania

  • jacek

    PODZIĘKOWAĆ na razie w operze i IE już działa tylko FF się buntuje

  • Łukasz

    Mam pytanie w jaki sposób przerobić to aby były np tylko 2 menu? bo teraz są trzy 😉