Załóżmy, że menu naszej strony WWW zrealizowaliśmy jako aktywną mapę (image map). (Nie wiesz co to jest aktywna mapa? za chwilę to wyjaśnimy.) Chcemy, aby poszczególne obszary reagowały zmianą wyglądu na pojawienie się nad nimi wskaźnika myszy. Jak to zrobić? Pomysł wygląda następująco. Nakładamy na siebie trzy obrazki o tym samym rozmiarze. Pierwszy obrazek - ten na samym spodzie - to menu w wersji podstawowej. Środkowy obrazek zawiera wszystkie elementy w wersji aktywnej - takiej, jak mają wyglądać po wskazaniu myszką. Początkowo obrazek ten jest niewidoczny. Na wierzchu znajduje się obrazek przeźroczysty. Będzie on odpowiedzialny za sterowanie działaniem menu.
Po załadowaniu strony użytkownik zobaczy menu w wersji podstawowej. Po wskazaniu myszką aktywnego elementu pokaże się fragment środkowego obrazka i przysłoni znajdujący się pod nim fragment wersji podstawowej. Do realizacji tego zadania wykorzystamy przycinanie warstw (clipping).
Może brzmi to trochę skomplikowanie, ale - jak się zaraz okaże - nie wymaga dużego nakładu pracy. Gwarantujemy, że po przeczytaniu artykułu będziesz w stanie z powodzeniem zastosować rollover na własnej stronie.
Przykład tutaj. W oparciu o ten sam pomysł działa także graficzne menu w naszym serwisie.
Grafika
Będziemy potrzebować trzy obrazki: jeden z menu w wersji podstawowej, drugi w wersji aktywnej, trzeci przezroczysty. Na potrzeby artykułu zaprojektowaliśmy menu przedstawione na rysunkach 1a i 1b. Przeźroczysty obrazek znajdziesz tutaj (plik blank.gif). Jego wielkość jest nieistotna, możesz więc korzystać z niego wielokrotnie.
| Rysunek 1a Menu w wersji podstawowej |
Rysunek 1b Menu w wersji aktywnej |
![]() |
![]() |
Mapa
Dynamiczny rollover wykorzystuje element języka HTML, która nie wszystkim naszym Czytelnikom musi być znany - mapowanie obrazków. Mapowanie polega na podzieleniu obrazka na obszary, a następnie przypisaniu poszczególnym obszarom odnośników hipertekstowych. Po wymapowaniu obrazek stanowi więc zbiór odnośników.
Mapowanie jest czynnością pracochłonną, radzimy skorzystać z jednego z wielu programów shareware lub freeware. Programy takie pozwalają zaznaczać myszką obszary obrazka, które chcemy uaktywnić, a następnie generują kod HTML gotowy do wstawienia do własnej strony, np Coffee Cup Image Mapper, lub Spinel WebMapper, dostępne w dziale PROGRAMY mojego serwisu.
Na rysunku 2 pokazany został podział na obszary naszego przykładowego menu. Poniżej przedstawiamy odpowiadający mu kod HTML, który wstawiamy w sekcji BODY:
<MAP name="menuMap"> <area shape="RECT" coords=" 9, 5,229,130" href="#" alt=""> <area shape="RECT" coords="26,135,264,260" href="#" alt=""> <area shape="RECT" coords=" 9,270,253,394" href="#" alt=""> </MAP>
Zamiast znaków # należy wstawić właściwe nazwy dokumentów, do których prowadzić ma nasze menu.
Rysunek 2. Podział obrazka na obszary

Obrazek
Obrazek w wersji podstawowej umieszczamy w dokumencie HTML w sekcji BODY:
<IMG SRC="menu.gif" WIDTH=270 HEIGHT=400 BORDER=0 ALT="menu" NAME="menuImg" ID="menuImg" STYLE="position:relative" USEMAP="#menuMap">
Musimy pamiętać o ustawieniu wartości kilku ważnych atrybutów (w kodzie zostały wyróżnione). Atrybuty ID, NAME i STYLE pozwolą sprawdzić dokładną pozycję obrazka w dokumencie z poziomu skryptów. Znajomość współrzędnych położenia menu na stronie będzie nam potrzebna do pozycjonowania pozostałych obrazków. Atrybut USEMAP wiąże nasz obrazek ze zdefiniowaną mapą.
Bloki
Czas dodać do dokumentu kolejne bloki: aktywną wersję menu oraz przeźroczysty obrazek odpowiedzialny za obsługę zdarzeń. Oba elementy zostaną nałożone na menu podstawowe.
W sekcji HEAD deklarujemy style dla dwóch bloków. Jako że deklaracje są identyczne, połączyliśmy je w jedną regułę:
<STYLE type="text/css">
<!--
#menuonDiv, #menublankDiv {
position:absolute;
width:270; height:400;
clip:rect(0 270 400 0);
visibility:hidden;
}
-->
</STYLE>
Oba bloki mają dokładnie taki sam rozmiar jak menu podstawowe i początkowo są niewidoczne. Bloki te wstawimy do dokumentu w trochę nietypowy sposób. Na końcu sekcji BODY dodajemy następujący kod:
<SCRIPT language="JavaScript"
<!--
if(!ie || !nn4){
bloki = '<DIV id="menuonDiv"><img src="menuon.gif" width=270 height=400></DIV>';
bloki += '<DIV id="menublankDiv"><img src="blank.gif"';
bloki += ' width=270 height=400 border=0 usemap="#menuMap"></DIV>';
document.write(bloki);
}
//-->
</SCRIPT>
Na początku tego fragmentu kodu sprawdzamy, czy mamy do czynienia z przeglądarką obsługującą DHTML. Jeżeli tak, to definiujemy zmienną bloki, do której wpisujemy cały tekst, który chcemy umieścić w dokumencie. Instrukcja document.write() wstawia ten tekst do dokumentu. Taka konstrukcja spowoduje dodanie bloków z obrazkami tylko wtedy, gdy strona zostanie załadowana przez przeglądarkę czwartej generacji. Starsze przeglądarki po prostu zignorują cały fragment kodu JavaScript.
Warstwa zewnętrzna (menublankDiv) także została połączona z aktywną mapą (atrybut USEMAP). Ta warstwa w przeglądarkach czwartej generacji całkowicie przesłoni nasze menu podstawowe i to właśnie menublankDiv będzie sterować obsługą wszystkich zdarzeń.
PozycjaNa razie dodatkowe warstwy nie są umieszczone we właściwym miejscu strony (jeżeli nie wierzysz, usuń z deklaracji stylów regułę visibility:hidden i przekonaj się). Musimy z poziomu skryptów ustawić oba bloki w tym samym miejscu, co menu podstawowe.
Przesuniecie bloków na swoje miejsce jest czynnością jednorazową, którą wykonamy zaraz po załadowaniu całej strony. W sekcji HEAD dokumentu dodajemy następujący kod:
<SCRIPT language="JavaScript" src="biblioteka.js"></script>
<SCRIPT language="JavaScript">
<!--
nn4=(document.layers)?true:false;
ie4=(document.all)?true:false;
function init(){
if(!nn4 && !ie4) {
return;
}
if(nn4) {
l=document.images.menuImg.x;
t=document.images.menuImg.y;
} else if(ie4) {
l=menuImg.offsetLeft;
t=menuImg.offsetTop;
}
moveTo("menuonDiv",l,t);
moveTo("menublankDiv",l,t);
show("menublankDiv");
}
window.onload=init;
//-->
</SCRIPT>
Pierwsza linijka tego fragmentu kodu powoduje załadowanie biblioteki (biblioteka.js) zawierającej podstawowe funkcje DHTML. Szerzej o tych funkcjach pisaliśmy w poprzednich odcinkach. Bibliotekę znajdziesz tutaj. Nie zapomnij umieścić pliku biblioteki w tym samym katalogu, co tworzony dokument HTML!
Kolejne kilka linijek powinno być znakomicie znane naszym Czytelnikom. Rozpoznajemy tu typ przeglądarki. Zaraz po załadowaniu całej strony przeglądarka wywoła funkcję init() (instrukcja window.onload = init;). Jeżeli przeglądarka nie jest zgodna ani z NN4, ani z IE4 (czyli jest to jakaś starsza przeglądarka), to natychmiast kończymy działanie funkcji init() (instrukcja return;) W przeciwnym razie zabieramy się za pozycjonowanie bloków.
Definiujemy dwie zmienne: l (left) i t (top), do których zapisujemy aktualną pozycje obrazka menuImg (menu w wersji podstawowej). Tutaj właśnie są potrzebne atrybuty NAME i ID zdefiniowane dla obrazka menu.gif. Dla bardziej dociekliwych: atrybut NAME jest wykorzystywany przez Navigatora, a ID przez Explorera.
Gdy znamy już aktualne położenie menuImg na stronie, przesuwamy obie warstwy na z góry upatrzone pozycje za pomocą funkcji moveTo(). Na koniec pokazujemy blok menublankDiv (funkcja show()). Od tej pory to obrazek znajdujący się w tym bloku jest odpowiedzialny za obsługę zdarzeń na stronie (bo jest na wierzchu).
Sterowanie
Teraz należy przygotować funkcje sterujące efektem rollover. Dla przypomnienia: chodzi o to, aby w momencie wskazania myszką aktywnego obszaru menu pokazać fragment środkowego bloku - aktywnej wersji menu. Odsłaniać będziemy prostokątne kawałki bloku - takie jak zdefiniowaliśmy w mapie. Do pokazywania części obrazka wykorzystujemy przycinanie (clipping).
W sekcji skryptu naszego dokumentu dodajemy kolejne dwie funkcje:
function menuOn(x1,y1,x2,y2) {
if(!nn4 && !ie4) {
return;
}
clipTo("menuonDiv",y1,x2,y2,x1);
show("menuonDiv");
}
function menuOff() {
if(!nn4 && !ie4) {
return;
}
hide("menuonDiv");
}
Pierwsza funkcja służy do pokazania fragmentu środkowego bloku (menuonDiv). Zaczynamy od sprawdzenia, czy pracujemy z przeglądarką czwartej generacji i jeżeli nie, to szybko kończymy działanie funkcji (dlaczego wykonujemy to sprawdzenie? o tym za moment). Następnie za pomocą funkcji bibliotecznej clipTo() przycinamy menu aktywne do odpowiedniego obszaru (prosimy zwrócić uwagę na kolejność argumentów w tej funkcji). Na zakończenie pokazujemy blok. W efekcie na stronie pokazana zostaje część menu aktywnego, która przesłania menu w wersji podstawowej. Funkcję będziemy wywoływać za każdym razem, gdy wskaźnik myszki znajdzie się nad obszarem aktywnym menu.
Druga funkcja jest jeszcze prostsza: ukrywa środkową warstwę. Funkcję tę będziemy wywoływać w momencie wyjścia wskaźnika myszki poza obszar aktywny menu.
ZdarzeniaNa zakończenie pozostało nam powiązać funkcje sterujące menuOn() i menuOff() z naszym menu. Zrealizujemy to wykorzystując zdarzenia. Zdarzenia to najrozmaitsze historie, które zachodzą podczas życia strony w przeglądarce. Już od kilku odcinków naszej serii obsługujemy jedno ze zdarzeń, mianowicie zdarzenie załadowania się strony do przeglądarki (onLoad).
Obecnie zdefiniujemy obsługę onMouseOver i onMouseOut, czyli zdarzenia najechania myszką na jakiś element menu i zdarzenia odwrotnego.
Modyfikujemy deklarację aktywnej mapy, dodając obsługę zdarzeń:
<MAP name="menuMap"> <area shape="RECT" coords=" 9, 5,229,130" href="#" alt="" onMouseOver="menuOn( 9, 5,229,130)" onMouseOut="menuOff()"> <area shape="RECT" coords="26,135,264,260" href="#" alt="" onMouseOver="menuOn(26,135,264,260)" onMouseOut="menuOff()"> <area shape="RECT" coords=" 9,270,253,394" href="#" alt="" onMouseOver="menuOn( 9,270,253,394)" onMouseOut="menuOff()"> </MAP>
Dla każdego obszaru przypisujemy do zdarzenia onMouseOver wywołanie funkcji menuOn(). Parametrami są współrzędne prostokąta, do którego przytniemy nasze aktywne menu. Są to dokładnie takie same wartości, jak współrzędne obszarów w aktywnej mapie. Zdarzenie onMouseOut wywołuje bezparametrową funkcję menuOff().
Niektóre starsze przeglądarki także obsługują zdarzenia onMouseOver i onMouseOut (a z tej samej mapy korzystamy także w tych przeglądarkach). W funkcjach menuOn() i menuOff() musimy zatem sprawdzić, z jaką przeglądarką pracujemy, aby nie kazać starszej przeglądarce wykonać czegoś, czego nie potrafi (przycięcie, odsłonięcie, ukrycie bloku).
I to już wszystko!Nadszedł czas na podziwianie efektów naszej pracy. Listing poniżej zawiera kompletny kod opisanego przykładu.
<HTML>
<HEAD>
<TITLE>Dynamiczny Rollover</TITLE>
<SCRIPT language="JavaScript" src="biblioteka.js"></SCRIPT>
<SCRIPT language="JavaScript">
<!--
nn4=(document.layers)?true:false;
ie4=(document.all)?true:false;
function init() {
if(!ie4 && !nn4) { return; }
if(nn4) {
l=document.images.menuImg.x;
t=document.images.menuImg.y;
} else if(ie4) {
l=menuImg.offsetLeft;
t=menuImg.offsetTop;
}
moveTo("menuonDiv",l,t);
moveTo("menublankDiv",l,t);
show("menublankDiv");
}
window.onload=init;
function menuOn(x1,y1,x2,y2) {
if(!nn4 && !ie4) { return; }
clipTo("menuonDiv",y1,x2,y2,x1);
show("menuonDiv");
}
function menuOff() {
if(!nn4 && !ie4) { return; }
hide("menuonDiv");
}
//-->
</SCRIPT>
<STYLE type="text/css">
<!--
#menuonDiv, #menublankDiv {
position:absolute;
width:270; height:400;
clip:rect(0 270 400 0);
visibility:hidden;
}
-->
</STYLE>
</HEAD>
<BODY>
<IMG src="menu_off.gif" width=270 height=400 border=0 alt="" name="menuImg"
id="menuImg" style="position:relative" usemap="#menuMap">
<MAP name="menuMap">
<area shape="RECT" coords=" 9, 5,229,130" href="#" alt=""
onMouseOver="menuOn( 9, 5,229,130)" onMouseOut="menuOff()">
<area shape="RECT" coords="26,135,264,260" href="#" alt=""
onMouseOver="menuOn(26,135,264,260)" onMouseOut="menuOff()">
<area shape="RECT" coords=" 9,270,253,394" href="#" alt=""
onMouseOver="menuOn( 9,270,253,394)" onMouseOut="menuOff()">
</MAP>
<SCRIPT language="JavaScript">
<!--
if(!ie || !nn4){
bloki = '<DIV id="menuonDiv"><img src="menuon.gif" width=270 height=400></DIV>';
bloki += '<DIV id="menublankDiv"><img src="blank.gif"';
bloki += ' width=270 height=400 border=0 usemap="#menuMap"></DIV>';
document.write(bloki);
}
//-->
</SCRIPT>
</BODY>
</HTML>
Jeszcze kilka uwag
Stworzony w tym odcinku skrypt nadaje się do natychmiastowego zastosowania na dowolnej stronie DHTML. Jedyne elementy, które wymagają dostosowania do konkretnych potrzeb, to nazwy i wymiary obrazków, adresy ładowanych dokumentów oraz współrzędne aktywnych obszarów. Przygotowany skrypt jest kompatybilny ze wszystkimi przeglądarkami. W starszych przeglądarkach menu będzie wprawdzie statyczne, ale będzie poprawnie spełniać swoją funkcję i użytkownik nie zobaczy żadnych błędów.
Opisana technika jest szczególnie użyteczna w przypadku, gdy chcemy stworzyć obszar z wieloma aktywnymi elementami. Wówczas tradycyjny rollover z podmianą obrazków wymaga przygotowania bardzo wielu obrazków, co sprawia, że strona może się znacznie wolniej ładować (więcej odwołań do serwera).
W naszym przykładzie współrzędne aktywnych obszarów i współrzędne atrybutu clip pokrywały się. Nie jest to jednak warunek konieczny. Często będziemy na przykład chcieli, aby obszary reagujące na ruchy myszy nie były prostokątami. Nic nie stoi na przeszkodzie, aby były to kółka lub dowolne wielokąty.
Na pierwszy rzut oka poważnym ograniczeniem jest fakt, że przycinać warstwy możemy wyłącznie do prostokąta. Powoduje to, że aktywne wersje elementów obrazka muszą być zawarte w rozłącznych prostokątach. Jednak przy odrobinie wysiłku można obejść także i to ograniczenie. Możemy dodać więcej warstw pomiędzy blokiem podstawowym a przezroczystym i umieścić aktywne wersje elementów na kilku warstwach. Będą wtedy mogły dowolnie na siebie zachodzić.