Praktyczne wprowadzenie do JavaScript #19

JavaScript to dynamizm, a jednymi z najbardziej dynamicznych elementów stron WWW są animacje. Te proste, jak i bardziej efektowne i skomplikowane. Język JS pozwala stworzyć (manipulując głównie stylami CSS) wiele ciekawych efektów, które są z reguły charakterystyczne dla animacji Flash i innych technologii animujących. Przypatrzmy się więc dokładnie temu zagadnieniu.

Screencast z tego odcinka znajdziecie tutaj, natomiast przykłady na żywo tutaj i tutaj.

Jedną z najprostszych animacji, jakie przychodzą do głowy, jest tzw. „miganie” tekstu. Po prostu co jakiś czas dany tekst pokazuje się, bądź chowa i tak w kółko. Aby wykonać coś podobnego, posłuży nam w głównej mierze ten szablon HTML:

<!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" lang="pl-PL">
<head>
<title>Strona z animacją</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf8" />

<!-- Nasz kod Javascript: -->

<script type="text/javascript">


</script>

</head>
<body>
	<div>
		<span id="napis">Odwiedzam Ferrante.pl i jest mi z tym dobrze ;-)</span>
	</div>
</body>
</html>

Gdybyśmy chcieli, aby ten oto element: <span id=”napis”>Odwiedzam Ferrante.pl i jest mi z tym dobrze ;-)</span> ukrywał się, z pewnością potrafilibyśmy mu nadać przez JS style display równy none. To samo byłoby w przypadku pokazania elementu (block/inline). Jak jednak sprawić, by sekwencje te wykonywały się po sobie? Powiedzmy, że napisalibyśmy funkcję, która w zależności od stylu display elementu span, ustawiłaby go na none bądź inline – zupełnie analogiczna sytuacja do odcinka z odsłanianiem akapitu w pierwszych częściach kursu. Problem polega jednak na tym, by sprawić, że owa funkcja będzie wykonywać się co jakiś czas, tak by spowodować mruganie tekstu. Popatrzmy:

Zaimplementujmy najpierw funkcję Animuj. Nie będzie to nic trudnego.

	function Animuj()
	{
		var span = document.getElementById('napis').style.display;
		if (span == "none")
		{
			document.getElementById('napis').style.display = "inline";
		}
		else
		{
			document.getElementById('napis').style.display = "none";
		}
	}

W pierwszej linijce pobieramy do zmiennej span wartość style.display elementu o id równym napis. Jak dobrze widzimy w dokumencie, zawiera on tekst, który chcemy animować. Następnie sprawdzamy wartość tej zmiennej. Możliwości są dwie – albo będzie to none albo inline. Dzięki instrukcji warunkowej if sprawdzamy obie możliwości, to znaczy:

Jeśli wartość zmiennej span jest równa none, pokaż tekst (ustaw style display na „inline”). W innym razie ukryj tekst (ustaw style display na „none”).

window.setInterval(„nazwafunkcji()”, opóźnienie)

Przykładowe wywołanie:

window.setInterval(„ostrzegaj()”, 2000);

Uruchomi funkcję o nazwie ostrzegaj co dwie sekundy.

No i w zasadzie wszystko byłoby w porządku, gdyby nie fakt, że nie wiemy, jak uruchamiać naszą funkcję co sekundę. Z pomocą przychodzi tu nam funkcja związana z oknem przeglądarki window, która potrafi uruchamiać dane funkcje w równym odstępie czasowym. Mowa o window.setInterval.

Funkcja ta w magicznie prosty sposób załatwia nam problem. Jak widzisz drogi Czytelniku, wymaga ona dwóch argumentów pomiędzy nawiasami. Pierwszy z nich to nazwa funkcji, którą chcemy uruchamiać z pewnym opóźnieniem czasowym. Wymaga się, aby była zapisana pomiędzy cudzysłowami oraz wraz z nawiasami, oznaczającymi jej wywołanie. Drugi argument to wspomniany przedział czasowy, podawany, uwaga, w milisekundach, które są tysiącznymi częściami sekundy. W związku z tym, opóźnienie dwusekundowe będzie wyrażone liczbą 2000.

Dodajmy więc odpowiednie wywołanie dla naszego skryptu, najlepiej na jego końcu, tak by wszystkie funkcje były już wcześniej w pamięci przeglądarki.

<!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" lang="pl-PL">
<head>
<title>Strona z animacją</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf8" />

<!-- Nasz kod Javascript: -->

<script type="text/javascript">

	function Animuj()
	{
		var span = document.getElementById('napis').style.display;
		if (span == "none")
		{
			document.getElementById('napis').style.display = "inline";
		}
		else
		{
			document.getElementById('napis').style.display = "none";
		}
	}

	window.setInterval("Animuj()", 1000);


</script>

</head>
<body>
	<div>
		<span id="napis">Odwiedzam Ferrante.pl i jest mi z tym dobrze ;-)</span>
	</div>
</body>
</html>

Poniższa linijka okazuje się zbawienna:

window.setInterval("Animuj()", 1000);

Wywołujemy tym samym funkcję Animuj co sekundę (1000 milisekund). Działa!

<marquee> do kosza!

Jak zapewne wiecie, stosując XHTMLową składnie, znacznik <marquee> jest niepoprawny. Używając JavaScript można jednak uzyskać podobną funkcjonalność. Wielkość kodu będzie stosunkowo niewielka i w głównej mierze zależy od ilości opcji. My zajmiemy się najuboższą wersją znacznika (inaczej przykład mógłby się okazać jak na warunki kursu zbyt skomplikowany), gdzie tekst przesuwać będzie się od prawej do lewej, z jednego miejsca.

Dokument HTML będzie wyglądał następująco:

<!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" lang="pl-PL">
<head>
<title>Strona z animacją</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf8" />

<!-- Nasz kod Javascript: -->

<script type="text/javascript">


</script>

</head>
<body>

	<div id="napis" style="left: 250px; position: absolute;">Odwiedzam Ferrante.pl i jest mi z tym dobrze ;-)</div>

</body>
</html>

Jak widać, do dyspozycji mamy teraz <div id=”napis”>. Skrypt będzie go musiał przesuwać co jakiś czas o kilka pixeli w lewo. Jak łatwo zauważyć, odbywać się to będzie poprzez zmniejszanie stylu left dla tego elementu. Popatrzmy:

Zaprezentowany sposób ma jednak wadę – napis będzie przesuwał się w nieskończoność w lewo… Dodamy więc stosowny warunek, który przesunie napis do początkowej pozycji (250px od lewej), kiedy właściwość left będzie mniejsza niż 50 pixeli.

Pora więc zabrać się za dodanie odpowiednich linijek skryptu. Najpierw dodajmy spokojnie funkcję setInterval:

<script type="text/javascript">

window.setInterval("Animuj()", 100);

</script>

Standardowo.

Pora teraz na zdeklarowanie funkcji Animuj:

function Animuj()
{
	var div = document.getElementById('napis');

	if (div.style.left < 50)
	{
		div.style.left = "250px";
	}
	else
	{
		div.style.left = (div.style.left - 3)+"px";
	}
}

Tak jak ustaliliśmy, najpierw pobieramy odnośnik do diva o id równym napis. Potem sprawdzamy, czy właściwość styli tego diva, a konkretnie left jest mniejsze niż 50. Jeśli tak, ustawiamy element do pierwotnej pozycji, przypisując właściwości left początkowe 250px. Jeśli jest inaczej (czyli div powinien być przesuwany dalej) odejmujemy od aktualnej wartości lewego odstępu 3. Warto spojrzeć na zapis tego działania:

div.style.left = (div.style.left - 3)+"px";

+"px"; oznacza, że do otrzymanej wartości liczbowej dopisujemy z prawej strony ciąg znaków px. Nie powinno to Cię zbytnio dziwić, albowiem nie zapisujemy w stylach left: 250; tylko left: 250px;.

W ten sposób uzyskaliśmy coś takiego:

<!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" lang="pl-PL">
<head>
<title>Strona z formularzem</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf8" />

<!-- Nasz kod Javascript: -->
<style type="text/css">
#napis
{
	position: absolute;
}
</style>
<script type="text/javascript">

	function Animuj()
	{
		var div = document.getElementById('napis');

		if (div.style.left < 50)
		{
			div.style.left = "250px";
		}
		else
		{
			div.style.left = (div.style.left - 3)+"px";
		}
	}

	window.setInterval("Animuj()", 100);

</script>

</head>
<body>
	
	<div id="napis" style="left: 250px;">Odwiedzam Ferrante.pl i jest mi z tym dobrze ;-)</div>
	
</body>
</html>

Pojawia się jednak błąd. Konsola błędów wskazuje na linijkę 28, czyli następującą:

div.style.left = (div.style.left - 3)+"px";

Patrzymy na ten zapis i nie widzimy w nim nic błędnego. Jedyne, co może komplikować sprawę to div.style.left (reszta to zwykłe liczby i konstrukcje języka, a pod tym zapisem nie wiemy tak naprawdę, co może się kryć, stąd też wskazanie na div.style.left). Sprawdźmy zawartość tej zmiennej:

function Animuj()
{
	var div = document.getElementById('napis');

	if (div.style.left < 50)
	{
		div.style.left = "250px";
	}
	else
	{
		alert(div.style.left);
		div.style.left = (div.style.left - 3)+"px";
	}
}

Dodaliśmy dla upewnienia się okienko alert. Jak widać, pokazuje one wartość 250px. Dochodzimy więc do wniosku, że div.style.left wstawione do alerta ma, rzecz jasna, wartość 250px. Podstawiając tą wartość do linijki nr 28, wyszłoby nam coś takiego:

div.style.left = (250px - 3)+"px";
parseInt(ciąg znakowy)

Zamienia ciąg znakowy zawierający liczby w wartość typu stricte liczbowego.

Na przykład alert(parseInt("17-letnia Ania")); zwróci liczbę 17.

Warto dodać, że zapis parseInt("Ania ma 17 lat"); zwróci błąd - funkcja ta nie da sobie rady z takim zapisem. Używamy więc jej, mając przed sobą ciąg rozpoczynający się od cyfr.

Jak widać, zapis 250px - 3 jest nieprawidłowy. Otóż 250px, jako że zawiera litery, jest ciągiem, a 3 oczywiście liczbą. Nie można więc, dajmy na to, od zdania czy wyrazu czegokolwiek odejmować. Trzeba zamienić ów wyraz (250px) na liczbę. W tym celu posłuży nam funkcja wbudowana w język JavaScript: parseInt.

Warto dodać, że nie łączymy ją z żadnym rodzicem (obiektem - już niedługo wytłumaczymy, co to znaczy). Nie spotkasz się więc nigdy z zapisem window.parseInt czy document.parseInt.

Pora więc nanieść odpowiednie zmiany do naszej funkcji:

function Animuj()
{
	var div = document.getElementById('napis');

	if (div.style.left < 50)
	{
		div.style.left = "250px";
	}
	else
	{
		div.style.left = (parseInt(div.style.left) - 3)+"px";
	}
}

Warto też to zrobić w argumencie warunku if, bo tam również skrypt sprawdza wartość left, a ta zapisywana jest przecież w stylu LICZBApx.

function Animuj()
{
	var div = document.getElementById('napis');

	if (parseInt(div.style.left) < 50)
	{
		div.style.left = "250px";
	}
	else
	{
		div.style.left = (parseInt(div.style.left) - 3)+"px";
	}
}

Tym sposobem doszliśmy do upragnionego finału:

<!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" lang="pl-PL">
<head>
<title>Strona z formularzem</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf8" />

<!-- Nasz kod Javascript: -->
<style type="text/css">
#napis
{
	position: absolute;
}
</style>
<script type="text/javascript">

	function Animuj()
	{
		var div = document.getElementById('napis');

		if (parseInt(div.style.left) < 50)
		{
			div.style.left = "250px";
		}
		else
		{
			div.style.left = (parseInt(div.style.left) - 3)+"px";
		}
	}

	window.setInterval("Animuj()", 100);

</script>

</head>
<body>
	
	<div id="napis" style="left: 250px;">Odwiedzam Ferrante.pl i jest mi z tym dobrze ;-)</div>
	
</body>
</html>

Oczywiście można dowolnie zmniejszać maksimum przesunięcia (250 pixeli) oraz częstotliwość. Wszystko zależy od odpowiednich argumentów dla funkcji setInterval oraz liczby pixeli odejmowanych co przesunięcie.

I tym miłym akcentem kończymy 19. odcinek Praktycznego wprowadzenia. Zapraszam do jubileuszowego, 20. odcinka już wkrótce!

Komentarze

1

Super, super, super – czekalem na to 18 odcinkow i w koncu sie doczekalem. Wreszcie naucze sie samodzielnie pisac jakies animacje, moze za iles kolejnych odcinkow uda sie zmotac cus a’la rybie oko, fade, slide itp ;)

Co do calosci kursu – jest swietny. Z poczatku troche sie denerwowalem powtarzalnoscia listingow i lopatologicznym tlumaczeniem, poniewaz mocne podstawy mialem ale doszedlem do wniosku, ze nie jestem sam. Im dalej jednak tym bardziej mi sie to wszystko podoba.

Rzecz ktorej obecnie mi brakuje to brak kolorowania skladni (i tak drukuje strone na czarno-bialej drukarce, mimo to fajnie by bylo;P ) oraz pdf’ow po kilka odcinkow. To jednak tylko sprawy techniczne. Wartosc merytoryczna jest swietna!!!!!!!!!!

Ithanoss
2

najlepszy kurs, jaki do tej pory było mi dane czytać :)
z niecierpliwością czekam na kolejne odcinki, pozdro

misiek_giz
3

Dziekuje za pozytywne opinie :-)

Pozdrawiam

4

i tak roztocze jest nasze!

Radek
5

[…] Na końcu uruchamiamy odpowiednie funkcje, o których już mówiliśmy, z pewnym, cyklicznym opóźnieniem. Wszystko dzięki setInterval, o którym pisałem choćby tutaj. […]

6

lepiej zamaist var span = document.getElementById(‚napis’).style.display; dać var span = document.getElementById(‚napis’) a pozniej jedziemy ze span.style.display

ziko
7

Nie siej herezji, Twoj przyklad to raczej afirmacja wolnosci wyboru, anizeli w istocie lepszych rozwiazan.

8

sam nie siej herezji lolu

fffffffff
9

Wszystko super, tylko dlaczego nie działa z left ustawionym w nagłówku ? Słyszałem o getComutedStyle, który sobie radzi w takich sytuacjach lecz zastanawia mnie dlaczego nie jest to tu poruszone, przecież o wiele bardziej popularne jest definiowanie styli w nagłówku a nie w pojedyńczych obiektach

10

Właśnie przeanalizowałem twój kod. Wielkie dzięki za pomoc, właśnie tego szukałem, ale nurtuje mnie jedna kwestia. Funkcja setInterval() jest, możnaby powiedzieć, zabójcza, bo nigdy się nie kończy. Owszem, ustawiamy warunek, dokąd napis ma się przesuwać, ale potem wraca on do początkowej pozycji i jedzie od nowa. setInterval() działa jak jakaś pętla bez warunku końcowego. Jak zatem zatrzymać tą funkcję po dotarciu napisu do lewej krawędzi dokumentu?

Dodaj komentarz

Dozwolone tagi: <blockquote>, <code>, <strong>