 |
Aquest exemple fa un intercanvi d'imatges fusionant-les
entre si. Tot l'efecte consisteix en manipular amb JavaScript les propietats
de dos objectes "Image". Les propietats que es manipulen en
temps de visualització són l'alçada (height),
l'amplada (width) i la seva coordenada Z (z-index).
Les dues imatges estan situades en el mateix espai físic. Mentre
una imatge va augmentant la mida, l'altra la va disminuint. Al mateix
temps, van alternant la seva coordenada Z per evitar que una d'elles quedi
definitivament amagada a sota.
Aquest efecte no funciona amb NN4. Per tant, si detectem que utilitzem
aquest navegador mostrarem un contingut alternatiu. Aquest contingut ha
d'ésser una alternativa, per tant, si es considera convenient,
es pot substituir per alguna altra imatge estàtica.
Tot i que pot funcionar amb els navegadors IE i NN6, la forma d'implementar-lo
és diferent. Ajustar aquesta incompatibilitat és el més
complicat del codi.
Dins el codi, a les línies 7-9, detectem el tipus de navegador
i dins el bloc <body> creem la pàgina d'una forma o una altra
segons sigui el navegador (el codi dins el bloc <body> pot anar
conjuntament a un altre codi HTML convencional). Les línies 41-51
creen el contingut, si el navegador és NN4, solament s'escriu un
text alternatiu d'avís (línia 42), aquest text es pot substituir
per algun altre contingut alternatiu.
Les línies 43 a 50 creen el contingut en cas que sigui un navegador
NN6 o IE. Aquest contingut consisteix en definir dues imatges amb identificadors
img1 i img2 i una capa que conté el botó de
commutació. Observeu com les línies 43-50 són la
continuació de la cadena iniciada dins de "document.write",
per clarificar-ho, s'ha posat la cadena en línies diferents, però,
per indicar a l'intèrpret Javascript que la cadena continua a la
línia següent, s'afegeix el símbol " \ "en
el lloc d'on es parteix.
Les línies 2,3 i 4 defineixen les propietats CSS per a les dues
imatges i la capa. La capa botocambia no té cap utilitat
en l' efecte del programa, solament s'utilitza per facilitar el posicionament
del botó de commutació.
L'accés a les propietats dels objectes es fa de forma diferent
amb NN6 i IE. Per exemple:
- Per llegir el valor de la propietat height, width
o zIndex d'un objecte Image es fa així:
Per a IE: document.all.ObjecteImage.propietat
Per a NS6: document.ObjecteImage.propietat
- Per assignar un valor a les propietats height,
width o zIndex de l'objecte Image es
fa així:
Per a IE: document.all.ObjecteImage.style.propietat
= ...
Per a NS6: document.getElementById('ObjecteImage').style.propietat
= ...
Com es pot veure són formes totalment diferents de llegir o assignar
valors segons sigui el navegador, ja que la manera de referenciar l'objecte
és molt diferent. La funció refObj() és l'encarregada
de facilitar aquestes incompatibilitats. Si la invoquem, ens retorna una
cadena per referenciar l'objecte adequadament, segons quin sigui el
navegador emprat i segons si volem llegir un paràmetre o el volem
modificar (en aquest últim cas hem de passar-li el nom de l'objecte).
La creació de la modificació d'una propietat es fa conjuntament
entre la invocació de refObj(), que retorna una cadena,
i la concatenació de la resta de paràmetres per formar la
cadena. Un cop creada tota la cadena, amb l'ajut de la funció eval(),
s'executa el seu contingut. Tal com es pot veure a les línies 17-21,
25-31 i 34-35
La funció cambia() és l'encarregada de fer la manipulació
de les propietats, ajudada per la funció refObj() per crear
les referències dels objectes. Es pren com a referència
les dimensions en píxels de les dues imatges, en aquest exemple:
img1 és 343x343 i img2 és 227x343 (les dues imatges poden
ser de la mateixa mida o diferent). Fixeu-vos com a la línia 3,
s'ha indicat per a la imatge 2 un ample i un alt inicial de 0px, és
a dir, inicialment la imatge 2 no existeix.
La variable booleana sentit representa quina és la imatge
que ha de créixer i decréixer en cada moment, inicialment
val true, això vol dir que la imatge 1 haurà de decréixer
i la 2 créixer, un cop feta la transició, s'inverteix el
valor d'aquesta variable a la línia 22.
Prenent com a referència la imatge 1, considerem sentit descendent
quan aquesta decreix (sentit=true) i ascendent quan aquesta augmenta
(sentit=false) i farem que aquesta modifiqui la seva mida en passos
de 5 píxels.
La condició de la línia 17 diu : quan imatge 1 decreixi,
si la seva alçada és inferior a 5 píxels o bé quan
imatge 2 decreixi i la seva alçada sigui inferior a 5 píxels
s'acaba la transició i s'assignen els valors finals a totes dues
imatges segons sigui el valor de sentit (línies 18-21).
En cas contrari, (línies 25-28) segons sigui el valor de sentit,
s'incrementarà o decreixerà el valor d'alçada i amplada
de la imatge 1 i 2 amb 5 píxels (excepte l'ample d'imatge 2, que
es farà en 3 píxels, ja que proporcionalment l'ample d'imatge
2 és inferior al d'imatge 1). També es farà,
a cada pas, un intercanvi de la propietat z-index per evitar que
una imatge quedi definitivament oculta per l'altra (línies 29-36).
També es programa un temporitzador (línia 37) per repetir
el mateix procés invocant la funció "cambia()",
al cap de 10 ms., mentre la imatge que decreix no valgui una alçada
inferior a 5 píxels.
El codi a implementar és el següent:
|
 |
En aquest apartat veurem com podem manipular els paràmetres
de les capes en temps de visualització, aconseguint efectes d'animació.
El codi de l'exemple és molt extens (242 línies), per aquest
motiu no s'ha inclòs en aquesta pàgina, per veure el codi,
heu de visualitzar la finestra de l'exemple i fent clic amb el botó
dret del ratolí sobre la finestra, seleccioneu la "Visualització
del Codi Font".
Tot i ser un exemple extens, es pot considerar com si fossin quatre exemples
diferents d'animació de capes. Els blocs de codi queden clarament
diferenciats ja que fan referència a una única capa de les
quatre de mostra.
Capa1.- Desplaçament lateral des de l'esquerra a petició
de l'usuari.
Capa2.- Capa que simula el comportament d'una finestra de Windows.
Inclou una capa enniuada de nom capa2a.
Capa3.- Capa superior que conté el títol, la seva
animació s'inicia automàticament en carregar la finestra
i es desplaça progressivament des de l'esquerra fins al centre.
Capa4.- Capa que conté una icona (smiley) que es mou constantment
per sobre de la pantalla rebotant aleatòriament en els marges.
L'animació s'inicia quan la capa3 s'ha posicionat en el centre
de la finestra.
Podem aïllar cadascun dels 4 exemples copiant les línies de
codi indicades a continuació en una pàgina web a part. En
la nova ubicació s'ha de respectar que també estiguin situades
dins els corresponents blocs <style> i <script> de <head>
i <body>.
- Comú a tots els exemples:
14-16.
- Capa1: línia 7, línies
17-41 i línies 195-212.
- Capa2: línies 8-9,
línies 42-112 i línies 213-234.
- Capa3: línia 10, línies
113-124 i línies 235-237.
- Capa4: línia 11, línies
125-191 i línies 238-240.
El codi indicat dins el bloc <body> i la definició d'estils
dins la directiva <style> del bloc <head> apliquen els objectes
HTML i els valors de les propietats que es veuen, per defecte, en carregar-se
la pàgina. En canvi, el codi, dins la directiva <script>
aplica la manipulació de les propietats dels objectes HTML en temps
de visualització, de manera que obtenim l'animació desitjada.
No es comentaran les diferents formes d'assignar o llegir valors de les
propietats dels objectes ja que tal com està fet el codi es pot
interpretar molt fàcilment quina és la forma pròpia
de cada navegador. Només cal distingir les línies començades
amb if (ie) .... ,
if (ns4) .... i if(ns6) ... que serveixen
per discriminar el codi propi per a cada navegador i interpretar la forma
en la qual es llegeix i s'assigna cada propietat.
Part comuna:
La part comuna a tot el codi són les línies 14-16, la seva
funció és detectar el tipus de navegador IE, NN4 o NN6 amb
què es visualitza la pàgina. Per això es testeja
l'existència dels objectes document.all, document.layers
i document.getElementById propis de cadascun dels navegadors indicats,
respectivament. La variable ie, ns4 o ns6 valdrà
true en el cas que sigui el navegador corresponent.
La detecció del navegador és necessària perquè
l'accés a les propietats de les capes i tractament d'events són
diferents per cada cas. Dins el codi propi de cada capa trobarem condicionals
que testegen aquestes variables i apliquen la manipulació de la
propietat corresponent amb el format apropiat, en cas contrari obtindríem
errors.
Aquesta forma de diferenciar la manipulació de les propietats no
és l'habitual en programació JavaScript, en aquest exemple
s'ha preferit fer-ho així per facilitar la llegibilitat del codi.
La forma habitual consisteix en la utilització d'una funció,
a la qual, passant-li els paràmetres corresponents retorni el codi
apropiat segons el tipus de navegador. Posteriorment s'avalua aquest codi
amb la funció eval(). A l'apartat anterior (exemple de commutació
d'imatges), en tenir un codi menys complex ja s'ha fet d'aquesta forma
utilitzant la funció refObj().
Si voleu aïllar el codi corresponent a un sol tipus de navegador,
només cal eliminar els blocs de codi que comencen amb if(tipusNavegador)
... , on tipusNavegador no correspongui amb el que voleu aïllar.
La resta de codi és comuna a tots els navegadors.
Capa1:
La capa1
està parcialment oculta en carregar-se la pàgina. Observeu
com a la línia 7 s'ha indicat una propietat left de -124px.
Per aquest motiu queda oculta a l'esquerra. Solament es veu una imatge
en forma de botó. La capa conté una taula per facilitar
el posicionament del text i la imatge.
La imatge "barra.gif" està dins un link nul (línies
206-208) que detecta l'event onClick. Aquest event invoca a la funció
obreTancaCapa1(). Observant el codi propi d'aquesta funció
(línies 17-41) tenim que inicialment s'ha declarat i assignat una
variable global i externa a la funció de nom estat amb el
valor false.
La variable estat indica si la capa esta oberta (true) o
tancada (false). Quan s'invoca la funció obreTancaCapa1(),
el primer que es fa és determinar el valor de la propietat left
de la capa segons sigui el tipus de navegador (línies 20-22)
i s'assigna a espaiEsq. Posteriorment es mira el valor d'estat
(línia 23), si val false s'inicia l'apertura de la capa1
(línies 33-39), si val true s'inicia el tancament de la
capa1 (línies 24-30).
L'obertura i tancament es fa en passos de 5 px, que s'afegeixen o resten
(línies 25-27 i 34-36) a la propietat left de la capa. A
cada increment o disminució efectuat s'activa un temporitzador
que tornarà a repetir el mateix procés (línies 28
i 37) fins que ja no es compleixin les condicions (espaiEsq > -124
i espaiEsq < 0, línies 24 i 33). En aquest moment es
considera que la capa ja està totalment oberta o tancada, solament
queda canviar el valor d'estat (línies 30 i 39) i ja s'atura
tot el procés fins que l'usuari desitgi tornar a obrir o tancar.
Capa3:
Aquesta
és la capa que conté el títol superior. El funcionament
de la capa3 és molt similar al de la capa 1, encara que més
senzill, perquè només es desplaça en un sentit. A
la línia 10 tenim la definició d'estils d'aquesta capa,
també podem veure com la propietat left està a -400
px, és a dir, totalment amagada a l'esquerra.
Al carregar la pàgina, s'activa automàticament l'event onLoad
(línia 194) que invoca la funció mouCapa3(). Aquesta
funció (línies 113-124) s'encarrega de desplaçar
la capa d'esquerra a dreta igual com ho fa la Capa1 quan s'obre.
El desplaçament es fa en unitats de 5px. Cada 100 ms. es torna
a invocar la funció (línia 121) i fa un pas més de
5 px, sumant-los a la variable capa3PosX que posteriorment s'assigna
a la propietat left de la capa (línies 117-120).
Quan s'arriba a la posició final (capa3PosX < 10, línia
116) finalitza el posicionament d'aquesta capa i s'inicia l'animació
de la Capa4 en invocar-la des de la línia 123. Si no es desitja
que s'iniciï l'animació de la Capa 4 solament fa falta eliminar
aquesta línia.
Capa4:
Aquesta capa és
la que correspon a l' "smiley" que està rebotant aleatòriament
per la finestra.
La capa està definida a les línies 238-240. El seu contingut
és una imatge de 16x16 px. La imatge forma part d'un link nul.
Si feu clic a sobre de la imatge (si ho podeu aconseguir ;-) ), s'atura
el moviment, ja que s'executa un clearTimeout() sobre la variable
sTO que conté l'identificador del temporitzador d'aquesta
capa.
L'estat inicial de la capa es defineix a la línia 11, observeu
com té una coordenada Z superior a les altres capes per fer que
sempre vagi per sobre d'elles i la seva visibilitat inicial és
oculta.
Quan finalitza el posicionament de la Capa3, s'invoca a la funció
mouCapa4() (línia 123). La funció mouCapa4()
(línies 125-191), s'encarrega de moure aleatòriament la
capa4 i el seu contingut. El seu moviment són desplaçaments
en línia recta fins a trobar un costat de la finestra on rebota.
Cada cop que rebota, canvia aleatòriament la seva trajectòria
i velocitat.
El primer que fa la funció mouCapa4() és determinar
la mida de la superfície disponible en el cos del document (línies
129-136) i ho assigna a les variables ampleBody i altBody.
En el cas que el mida de la finestra sigui més gran que el de l'objecte
que conté la capa (16x16, línia 137) es determina un valor
inicial aleatori capa4PosX i capa4PosY i es fa la capa visible
(línies 140-156).
Posteriorment, es determina un valor d'increment X i Y aleatori entre
1 i 11, i un signe d'aquest increment igual a -1 o 1 aleatori (línies
157-160). Finalment es posa la variable posCapa4 a false
(línia 161) perquè no es torni a efectuar aquest procés
i s'activa un temporitzador per tornar a invocar la funció al cap
de 50 ms. (línia 189).
Al tornar-se a executar la funció mouCapa4() (per la finalització
del temporitzador), es torna a verificar la mida de la finestra i es va
directament a la línia 164 on es comprova que la capa estigui
dins l'àrea de la finestra (línia 164).
Si s'està dins la finestra, es verifica si l'increment de coordenades
portarà la capa fora de la finestra, si és així,
es calcula de nou, aleatòriament els valors de l'increment i el
signe de desplaçament (línies 165-172). Un cop es té
un valor que no ens porti fora de la finestra, s'incrementa a capa4PosX
i capa4PosY i posteriorment s'assigna a les propietats left
i top de la capa4 (línies 173-186).
Globalmentl, l'efecte mostra una capa que es mou de forma rectilínia
dins la finestra, amb uns increments i signe de X i Y constants (velocitat
i angle constants), però que quan arriba al límit de la
finestra, es tornen a calcular aleatòriament els increments i signe
de X i Y, canviant la velocitat i l'angle aleatòriament respecte
a la trajectòria anterior.
Capa2:
La capa
2 és la més complexa de totes. Per aquest motiu s'ha deixat
pel final. De fet està formada per dues capes la capa2 i
la capa2a. Aquesta animació no és compatible amb
Netscape 4, per tant, si detectem aquest navegador s'haurà de mostrar
un contingut alternatiu.
En aquesta capa és necessari capturar els events onmousemove
i onmouseup, encara no s'ha explicat res sobre la captura d'events,
per tant, no s'explicarà amb detall. En la pràctica
1 del mòdul 7 s'explica com es capturen els events. Quan hagueu
fet aquesta pràctica, podeu tornar a aquest apartat i analitzar
amb més detall com es fa aquesta capa.
La definició de les propietats d'aquestes dues capes es fa a les línies 8 i 9, observeu com la capa2a té
un posicionament relatiu. Com que està situada dins la capa
2 les seves referències top i left tindran com
origen de coordenades les de la capa 2. La visibilitat de la capa2a
s'hereta de la capa2 i si el seu contingut és extens apareixeran
les barres de desplaçament (overflow:auto).
Aquestes dues capes es posicionen dins el bloc <body> a les línies
213-234. Observeu com la seva inclusió es fa a partir de codi JavaScript.
És necessari detectar el navegador, ja que si es tracta de NN4
no podem crear la capa2a perquè es veuria malament (línia
219). Per als altres dos navegadors IE i NN6, es crea el contingut de
la capa a les línies 221-231.
La variable de text txt, conté tot el contingut de la capa2
i la capa2a. Inicialment s'introdueixen tres imatges corresponents
a la capçalera de la capa, són la barra de títol,
el botó de minimitzar i el botó de tancar (línies
221-223). Posteriorment es crea la capa2a i el seu contingut (línies
224-230).
Les tres imatges de la capçalera responen a events introduïts
amb el ratolí. Quan es fa clic a sobre de la imatge
(capa2_3.jpg) s'invoca l'event onClick i es canvia la propietat
de visibilitat de la capa2 a oculta (línia 223). Si es fa
clic a la imatge
(capa2_2.jpg), s'invoca la funció minMaxCapa2() (línia
222), observeu que aquesta imatge té un identificador : id="imgMinMax",
aquest identificador servirà per poder canviar la imatge a
(capa2_4.jpg) a les línies 49 i 54, quan la capa2 sigui
minimitzada. Les línies 62 i 67 fan l'efecte contrari.
La imatge (capa2_1.jpg)
introduïda a la línia 221, també respon a un event,
en aquest cas l'event onMouseDown. Aquest event invoca la funció
mouCapa2(), que s'encarrega de capturar els events onmousemove
i onmouseup i permeten desplaçar la capa per sobre de la
finestra.
La funció minMaxCapa2() (línies 42-71) minimitza
o maximitza la capa2. Per això utilitza la variable global
minMax per saber si està oberta o tancada. Per tancar la
capa, posa a 0px l'alçada de la capa2a i a 23px/19px l'alçada
de la capa2, segons sigui per a IE o NN6. També canvia la
imatge amb identificador imgMinMax per mostrar l'altre símbol
alternatiu (línies 46-54).
En cas contrari, si s'ha d'obrir la capa, fa el mateix procés,
però a la inversa (línies 59-67). Per acabar cadascun dels
dos processos (obertura o tancament de la capa) es canvia el valor de
la variable minMax (línies 56-69).
La funció mouCapa2() és la responsable de facilitar
el desplaçament. Com ja s'ha dit manipula la captura dels events
onmousemove i onmouseup. A la pràctica
1 del mòdul 7 trobareu més informació sobre aquests
conceptes.
La incompatibilitat amb el Netscape 4 bé determinada per la utilització
de la capa2a enniuada dins la capa2. Aquest fet, més
la propietat overflow assignada a la capa2, fa que sigui
incompatible amb el NN4. Si aquest mateix exemple no contingues la capa2a
podria funcionar perfectament amb el NN4 ja que el sistema de captura
d'events és el mateix que s'ha aplicat pel cas del NN6.
|