INDEVELOPMENTbeta






Subskrybuj m1chu.eu – another devblog
 
  •  Marcin: Takie strony to jak to się mówi STATE OF THE ART… tu nie ma co komentować nawet…po prostu
  •  Michał: document.body.firstChild.appen dChild(p); chyba powinno być: document.body.firstChild.ap...
  •  michal: Witam Pilnie prosze Cie o kontakt mailowy w sprawie strony http://regexp.m1chu.eu/. Z gory dzieki za...
  •  Pawel: Witam Na stronie http://www.rozenek.com/polski, 198 opisalem podobny problem:...
  •  wwww: Geniusze IT w Warszawie http://capital24.tv/film/4c336 f2d7c878/geniusze_it_w_warszaw ie
  •  Kpc21: Na Operze 10.53 działa już w postaci docelowej, bez „-o-”.
  •  m1chu: Prawda, to nie są strony zbyt funkcjonalne. Dlatego większość z nich to portfolia/personalne...

Ankieta!

  • Jak oceniasz poziom artykułów? (dokładną opinię umieść w komentarzu)

    View Results

    Loading ... Loading ...




Efekt graficznego podświetlenia w jQuery i Prototype z Scriptaculous


Efekt podświetlania w jQuery i Prototype

Jedni nie korzystają z nich wcale, niektórzy tylko po to aby zwiększyć funkcjonalność tworzonych przez siebie stron, a u jeszcze innych zauważalny jest przepych tego typu rozwiązań. Biblioteki programistyczne języka JavaScript, bo o ich wykorzystaniu tu mowa to źródło bardzo różnorodnych, nie tylko funkcjonalnych, ale także estetycznych efektów. Sieć aż kipi od dobrych i słabych, lepiej oraz słabiej wytłumaczonych przykładów użycia możliwości MooTools, jQuery, Prototype z Scriptaculous, czy innych mniej powszechnych frameworków.

Jednym z takich efektów jest możliwość stworzenia animowanego, graficznego podświetlenia pojawiającego się np. nad grafiką wywołującą animację. Interaktywność taka została opisana na NetTuts z wykorzystaniem MooTools. My osiągniemy taki wynik dzięki zastosowaniu jQuery (w jednym przykładzie) oraz dodatkowo także za pomocą Prototype wraz z Scriptaculous (w drugim przykładzie).

Oczekiwany efekt
Oczekiwany efekt.

Krok 1: Za co się chwycić na początku…

Na początek musisz wiedzieć w jakim celu potrzebny jest Ci prezentowany w tym artykule efekt. Menu? Wyświetlanie dodatkowych informacji w graficznej liście produktów? Czy może szybki, animowany splash? Wybór jest Twój i podług niego będziesz musiał zaopatrzyć się w dodatkowe, niezbędne elementy do wykonania podświetlenia.

Chodzi tu mianowicie o grafiki, których musi być dwa razy więcej niż elementów podatnych na działanie mechanizmu. Powiedzmy, jeżeli chcemy w pięcioelementowym menu zastosować w każdym zdarzenie po najechaniu myszką zgodne z przesłaniem tego artykułu to potrzebujemy dziesięciu grafik. Pięć opisujących przyciski menu i drugie tyle będące „treścią” pojawiającą się po podświetleniu.

Po uporaniu się z wizualną częścią problemu oraz strony internetowej możemy ruszyć krok dalej.

Krok 2: Zaopatrujemy się w jQuery i/lub Prototype i Scriptaculous!

jQuery to aktualnie najpopularniejsza biblioteka. I najłatwiej ją skatalogować w czeluścia własnego projektu. Wystarczy ze strony głównej pobrać wersję 1.3.1 production/Minified i umieścić ją w obrębie plików tworzonego przez nas przykładu (niezbędny będzie tylko plik jquery-1.3.1.min.js).

Z Prototype sprawa jest ciut bardziej skomplikowana, bo prócz standardowego frameworka musimy pobrać także dodatkowy interfejs w postaci Scriptaculous, dzięki któremu uzyskamy dostęp do efektu pozwalającego na dynamiczne zmienianie właściwości CSS elementów strony. Ściągamy więc wersję 1.6.0.3 pierwszej biblioteki, oraz paczkę z wersją 1.8.2 drugiej. Z obydwu wyodrębniamy pliki i w ramach folderu tworzonego przez nas projektu umieszczamy tylko prototype.js oraz effects.js (z drugiego archiwum).

W przypadku tego artykułu umownie pliki związane z frameworkami będą znajdować się w podkatalogu javascript folderu głównego. Obydwa przykłady (dotyczące, jeden jQuery, a drugi Prototype z Scriptaculous) będą oczywiście wykonywane w osobnych plikach znajdujących się w dwóch różnych katalogach.

Rozdzielenie implementacji przykładów na dwa katalogi
Przykładowe rozdzielenie implementacji przykładów na dwa katalogi. W naszym przypadku pliki .js znajdują się dodatkowo w podkatalogu javascript.

Krok 3: Tworzymy strukturę XHTML

Atutem naszego rozwiązania jest kompatybilność z serwowaniem dokumentu XHTML w postaci application/xhtml+xml, czego bardzo często brakuje w przypadku efektów opartych na bibliotekach JS. Z racji tego także, że i w przypadku Prototype i jQuery struktura strony pozostaje niezmienna to obojętnie który framework wykorzystujesz poniższe tłumaczenie i partie kodu będą prawidłowe.

Z powodu tego w jaki sposób będziemy wysyłać treść strony posłużymy się małą częścią kodu PHP, a co za tym idzie plik korzystający z naszego mechanizmu musi mieć też takie rozszerzenie (no chyba, że serwer jest inaczej skonfigurowany, ale to już problematyka do rozwiązania na inny temat).

<?php
if ( stristr($_SERVER['HTTP_ACCEPT'], 'application/xhtml+xml') ) // jeżeli przeglądarka obsługuje application/xhtml+xml
{
	header("Content-Type: application/xhtml+xml; charset=utf-8"); // wysłanie odpowiednich nagłówków
	print '<?xml version="1.0" encoding="utf-8"?>'."\r\n";
	print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"'."\r\n";
	print '"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'."\r\n";
}
else // wysłanie dokumentu jako text/html dla przeglądarek nie obsługujących typu zawartości pliku z powyższego warunku, np. dla IE
{
	header("Content-Type: text/html; charset=utf-8");
	print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"'."\r\n";
	print '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'."\r\n";
}
?>

Poniżej dodajemy uniwersalny układ strony. Ważnym ułatwieniem jest możliwość tworzenia odnośników z elementów graficznych podatnych mechanizmowi, a także fakt, że nie korzystamy w nim z tagów img, a efektu zbliżonego do sliding-doors w celu wyświetlania obrazów.

<html lang="pl" xml:lang="pl" xmlns="http://www.w3.org/1999/xhtml">
<head>
	<meta http-equiv="Content-type" content="<?php print ( stristr($_SERVER['HTTP_ACCEPT'], 'application/xhtml+xml') ? 'application/xhtml+xml' : 'text/html' ); // typ zawartości zależny do możliwości przeglądarki użytkownika ?>; charset=utf-8" />
  	<meta name="Description" content="Product highlighter - tworzenie dynamicznych opisów produktów - m1chu.eu" />
  	<meta name="Keywords" content="product, highlighter" />
	<title>Product highlighter</title>
	<style type="text/css">@import url('stylesheet.css');</style> <!-- arkusz stylów -->
</head>
<body>
	<div id="siteContainer">
		<div id="highlightsContainer"> <!-- zbiór grafik wyświetlanych przy najechaniu kursorem -->
			<div class="highlights" id="highlight1"></div>
			<div class="highlights" id="highlight2"></div>
			<div class="highlights" id="highlight3"></div>
		</div>

		<div id="pageContainer"> <!-- zbiór grafik podatnych na efekt -->
			<div class="pages" id="page1"><a href="http://m1chu.eu/"></a></div>
			<div class="pages" id="page2"><a href="http://vivee.info/"></a></div>
			<div class="pages" id="page3"><a href="http://utnij.eu/"></a></div>
		</div>
	</div>
</body>
</html>

Krok 4: Stylizujemy strukturę strony za pomocą CSS

Posługując się metodami pozycjonowania elementów dostępnymi w kaskadowym arkuszu stylów możemy operując na elementach o identyfikatorach siteContainer, pageContainer, highlightsContainer oraz divach potomnych ułożyć i wystylizować wygląd, w tym położenie jak na wyżej zamieszczonym filmiku (screenie) obrazującym wykonanie zadania z tego artykułu.

Do wszystkich bloków kodu CSS odwołujących się do tagów zawierających identyfikatory grafik zostały dodane także właściwości background z adresem pliku tła.

W naszym przypadku poniższy kod zapisujemy do pliku stylesheet.css.

/* ustawienia domyślne dla ciała strony (w poprawnie wysyłanym XHTML jest to html+body, a nie tylko body) */
html, body {
	margin: 0px;
	padding: 0px;
	background: #000 url('bg.png') repeat-x;
}

#siteContainer {
	margin: 150px auto 0px auto; /* marginesy - wyśrodkowanie poziome */
	width: 573px;
	height: 345px;
	position: relative; /* relatywna pozycja, kontener */
	background: transparent url('container.png') no-repeat top left;
}
#pageContainer {
	position: absolute; /* pozycja względem #siteContainer */
	z-index: 5; /* ponad ciałem strony i pod #highlightsContainer */
	top: 128px;
	left: 0px;
}
#highlightsContainer {
	position: absolute; /* pozycja względem #siteContainer */
	z-index: 10; /* ponad pozostałymi elementami */
	left: 178px;
	top: 30px;
}
/* ustawienie w linii wraz z zmianą wyglądu kursora */
#pageContainer > div {
	float: left;
	cursor: pointer;
}
/* rozmiary klikalnych divów potomnych znajdujących się w kontenerze listy grafik podatnych na działanie mechanizmu */
#pageContainer > div a {
	width: 178px;
	height: 178px;
	display: block;
}
#page1 {
	margin-right: 19px; /* prawy margines - odstęp od kolejnego diva */
}
#page1 a {
	background: url('icon_1.png') no-repeat; /* tło grafiki podatnej na działanie efektu */
}
#page2 {
	margin-right: 20px; /* prawy margines - odstęp od kolejnego diva */
}
#page2 a {
	background: url('icon_2.png') no-repeat; /* tło grafiki podatnej na działanie efektu */
}
#page3 a {
	background: url('icon_3.png') no-repeat; /* tło grafiki podatnej na działanie efektu */
}

/* rozmiary wszystkich potomków typu div kontenera zawierającego podświetlenia */
#highlightsContainer > div {
	position: absolute;
	width: 222px;
	height: 101px;
	display: block;
}
/* pliki tła w pojawiających się podświetleniach */
#highlight1 {
	background: transparent url('highlights_1.png') no-repeat;
}
#highlight2 {
	background: transparent url('highlights_2.png') no-repeat;
}
#highlight3 {
	background: transparent url('highlights_3.png') no-repeat;
}

Krok 5a: Dodajemy jQuery do dokumentu

Tego, czego zabrakło dotychczasowo w naszym dokumencie to załączenie bibliotek oraz pliku .js w którym będzie znajdować się kod animujący pożądany przez nas efekt.

Dla jQuery w sekcji head należy dodać pliki jquery-1.3.1.min.js oraz product-highlighter.js (który umownie będzie zawierał dodatkowy kod).

	<script type="text/javascript" src="javascript/jquery-1.3.1.min.js"></script>
	<script type="text/javascript" src="javascript/product-highlighter.js"></script>

Krok 5b: Dodajemy Prototype z Scriptaculous do dokumentu

Tym razem musimy dodać jeden plik więcej. Bibliotekę (prototype.js), jej dodatkowy interfejs, a dokładniej plik zawierający obiekt Effect (effects.js) oraz jak w powyższym przypadku plik z naszym kodem animacji (product-highlighter.js).

		<script type="text/javascript" src="javascript/prototype.js"></script>
	<script type="text/javascript" src="javascript/effects.js"></script>
	<script type="text/javascript" src="javascript/product-highlighter.js"></script>

Krok 6a: Implementujemy kod animacji z użyciem jQuery

Jak to bywa w przypadku tego frameworka, aby jakieś zdarzenie działało poprawnie powinno się je umieszczać w funkcji $(document).ready(), której zawartość zostanie załadowana w momencie załadowania drzewa dokumentu.

$(document).ready(function() {
	[kod]
});

W [kod] musimy przypisać (do tablicy) wg. klasy wszystkie grafiki wyświetlane podczas podświetlenia, ustawić parametry podstawowe CSS oraz stworzyć sprawdzanie w pętli, czy dana grafika o klasie .pages nie jest najechana przez kursor i w zależności o danego trybu (kursor na/kursor poza) wykonać pożądaną animacji (wyłonienie dodatkowego tła / zanikanie dodatkowego tła).

Poniższy kod umieszczamy w pliku product-highlighter.js.

$(document).ready(function() {
	// tablica elementów o klasie .highlights
	var highlights = $('.highlights');

	// ustawienie pełnej przezroczystości elementów pojawiających się w czasie najechania myszką na obiekty podatne efektowi oraz widzialności ich kontenera
	$('.highlights').css('opacity', 0);
	$('#highlightsContainer').css('visibility', 'visible');

	// sprawdzanie każdego elementu podatnego mechanizmowi
	$('.pages').each(function(i) {
		// jeżeli na danym elemencie znajduje się kursor
		$(this).mouseover(function() {
			// wykonanie animacji grafiki wyłanianej i przypisanej do najechanego elementu (margines o 15px w górę i brak przezroczystości w czasie 0,5 sekundy)
			$(highlights[i]).animate({
				opacity: 1,
				marginTop: '-15px'
			}, 500);
		}).mouseout(function(){ // jeżeli na danym elemencie nie znajduje się już kursor
			$(highlights[i]).animate({
				opacity: 0,
				marginTop: '-0px'
			}, 500);
		});
	});
});

Należy jeszcze wyjaśnić dokładniej w jaki sposób działa $(highlights[i]).animate(). Mianowicie przy każdej iteracji pętli $('.pages').each() przekazuje ona do parametru function(i) aktualny numer elementu na którym się znajduje. Ponieważ w id pageContainer znaczniki potomne muszą być posegregowane i musi być ich tyle samo co obiektów graficznych w highlightsContainer to jeżeli kursor znajduje się na pierwszym podatnym na efekt obrazie to w podświetleniu wyłania się także pierwsza grafika. Wszystko to dzięki wyłuskaniu jej z tablicy highlights poprzez parametr i.

Krok 6b: Implementujemy kod animacji z użyciem Prototype z Scriptaculous

Event.observe – uchwyt rejestrujący zdarzenie na drzewie dokumentu. Funkcja obiektu składającego się na bibliotekę Prototype. Posiada cztery argumenty:
  • element – obserwowany element DOM, mogący być referencją do niego bądź jego identyfikatorem,
  • nazwaZdarzenia – standaryzowana wg. DOM Level 2 Events nazwa zdarzenia, np. load,
  • uchwyt – uchwyt w postaci funkcji.

Przykład:

<p id="test">Prototype</p>
Event.observe('test', 'click', function() {
	[kod]
});

Podobnie w Prototype obserwujemy zdarzenie, ale tym razem załadowania całej strony w celu późniejszej obserwacji aktywności kursora na wybranych elementach aktywnych. Można oczywiście podobnie jak w poprzednim podpunkcie wykonać obserwacje zdarzeń wraz z załadowanie DOM (drzewa dokumentu) poprzez użycie document.observe('dom:loaded', function() {}). To tylko kwestia osobistego wyboru.

Event.observe(window, 'load', function() {
	[kod]
});

Dalsze postępowanie jest adekwatne do tego opisanego w przypadku zastosowania jQuery. Z tymże, tablicę elementów o danej klasie pobiera się poprzez podwójny znak dolara ($$), a najechanie oraz zjechanie kursorem poza zadany obszar rozpoznaje się także poprzez obiekt Event i metodę observe(). Do animacji służy funkcja Morph instancji Effect z pliku effects.js interfejsu Scriptaculous.

Event.observe(window, 'load', function() {
	var highlights = $$('.highlights'); // utworzenie tablicy

	$$('.highlights').invoke('setStyle', { opacity: 0 }); // ustawienie stylu przezroczystości
	$$('#highlightsContainer').invoke('setStyle', { visibility: 'visible' }); // widzialność kontenera

	$$('.pages').each(function(v, i) { // pętla
		Event.observe(v, 'mouseover', function() { // zdarzenie wykonywane w momencie pojawienia się kursora na elemencie
			new Effect.Morph(highlights[i], { // animacja
				style: 'opacity: 1; margin-top: -15px;',
				duration: 0.5 // czas 0,5 sekundy
			});
		});
		Event.observe(v, 'mouseout', function() { // zdarzenie wykonywane w momencie wyjechania kursorem poza element
			new Effect.Morph(highlights[i], {
				style: 'opacity: 0; margin-top: 0px;',
				duration: 0.5
			});
		});
	});
});

Tym razem do funkcji w $$('.pages').each() przekazywane są dwa parametry: v i i. Pierwszy z nich jest odpowiednikiem this i wskazuje na aktualnie przetwarzany element tablicy znaczników o klasie .pages. Drugi to numer pokazujący który z kolei tag jest aktualnie sprawdzany. Inaczej pisząc jego zadanie jest równoznaczne do działania parametru i w przykładzie z jQuery.

Effect.Morph – metoda interfejsu Scriptaculous >= 1.7. Pozwala na animacyjną zmianę właściwości CSS elementu. Przyjmuje jeden podstawowy argument style zawierający w sobie właściwości i wartości CSS w formie oryginalnej bądź w postaci Camel-Case, czyli bez spacji i znaków specjalnych pomiędzy kilkoma członami nazwy właściwości. Opcjonalnie można dodawać kolejne parametry rdzenia obiektu Effect, takie jak duration (czas animacji), czy transition (rodzaj animacji, wymaga Effect.Transitions).

Przykład:

new Effect.Morph('div_id', {
	style: {
		background-color: '#000',
		color: '#fff'
	},
	duration: 0.5,
	transition: Effect.Transitions.spring
});

Demonstracja wyników…

Stworzyłem dwa gotowe przykłady, których analiza pozwoli Wam jeszcze bardziej zrozumieć jak stworzyć ten efekt. Pierwszy, za pomocą jQuery. Drugi, za pomocą Prototype z Scriptaculous.

Jeżeli chcecie dowiedzieć się więcej o tych bibliotekach to zapraszam do ich dokumentacji (Prototype, jQuery).


4 komentarzy

  • gravatar
    1. cloudi ()

    Taka mała uwaga: jak szybko sobie przejadę w te i we w te po divach „pages” będzie się animować do bólu, aż skończy się wszystko co jest w kolejce :)

  • gravatar
    2. m1chu ()

    Wystarczy dodać zdarzenie stop() przed animacją dla pojawienia się kursora nad obiektem i po jego zejściu. Czyli zamiast:

    jQuery(highlights[i]).animate({

    ->

    jQuery(highlights[i]).stop().animate({

    I zamiast:

    jQuery(highlights[i]).animate({

    ->

    jQuery(highlights[i]).stop().animate({

    Co do Prototype to powinien w standardzie działać lepiej pod tym względem niż jQ, nie mniej jednak można dodać także zdarzenia stop() przed wywołaniem Morph, a także dodać do parametr do function w observe w celu zatrzymania aktualnych animacji. Czyli zamieniamy:

    Event.observe(v, 'mouseover', function() {

    Na:

    Event.observe(v, 'mouseover', function(event) {
    			Event.stop(event);

    To samo robimy w observe -> mouseout.

    Powinno działać.

  • gravatar
    3. allplayer ()

    Gdzie na stronie mozna znaleźć maila do Ciebie ?

  • gravatar
    4. m1chu ()

    m1chu #at# m1chu #dot# eu (#at# = @, #dot# = . – bez spacji) ;]

    W gruncie rzeczy… tak jak patrzę, to niemożna znaleźć. Muszę to gdzieś umieścić… tylko jeszcze nie wiem gdzie ;]

Dodaj własny komentarz

Możesz użyć następujących tagów XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>