Uno degli aspetti più apprezzati di un framework Javascript è sicuramente la componente che riguarda la creazione e la composizione di effetti.
Nel Web 2.0 gli effetti DHTML sono una delle caratteristiche primarie, quella che permette di dare origine ad applicazioni di nuova generazione. Pensate ad esempio alle liste drag&drop dei siti di e-shopping che consentono di trascinare i prodotti all'interno di un carrello oppure rimuoverli, agli effetti "fade" e "toggle" che agiscono sulle proprietà CSS di un elemento facendolo scomparire/apparire con stile, o ancora all'apparizione di tooltips sulle immagini, allo smooth scrolling e cosi via.
MooTools offre un set completo per la creazione dei più comuni effetti DHTML e tutti gli strumenti necessari per crearne di personalizzati.
Negli articoli precedenti ho esposto parecchi cenni teorici sulle meccaniche di MooTools in modo da fornire le conoscenze necessarie per utilizzare i componenti più avanzati con maggiore dimestichezza. Nella prima parte di questo articolo spiegherò quali costrutti nativi MooTools offre per la creazione di effetti, mentre nella seconda parte la teoria lascierà largo spazio alla pratica: creeremo prima un effetto personalizzato, poi utilizzeremo una classe nativa per creare effetti a catena.
Gli effetti Fx
Il nucleo di effetti offerto da MooTools è basato sull'oggetto Fx, o meglio, sulla sua componente Fx.Base (che nella versione 1.2 verrà semplicmenete rinominata in "Fx"). La classe Fx.Base non deve essere utilizzata direttamente dall'utente, ma serve come wrapper per le altre componenti Fx (contiene metodi per il parsing dei valori CSS e opzioni di default che vengono ereditate) e va quindi sempre inserita nel download se si vogliono utilizzare gli effetti.
Nativamente MooTools ci offre cinque classi per creare effetti di alto livello: Fx.Style, Fx.Styles, Fx.Slide, Fx.Scroll e Fx.Elements (tralasciando tutti i plug-in che ne derivano, come Tips visto nell'articolo MooTools: usare i tooltips, Slider, etc.). Ognuna di esse eredita dal costruttore Fx.Base (http://docs.mootools.net/Effects/Fx-Base.js) le seguenti opzioni:
- onStart - una funzione che viene richiamata quando l'effetto inizia;
- onComplete - una funzione che viene richiamata quando l'effetto termina;
- onCancel - una funzione che viene eseguita quando l'effetto viene interrotto;
- unit - l'unità da utilizzare come valore delle proprietà CSS;
- fps - i frame per secondo;
- duration - la durata in ms dell'effetto;
- transition - l'equazione usata per modificare l'andamento dell'effetto (una delle Fx.Transitions).
Tutte possono essere impostate, utilizzate e personalizzate come abbiamo visto nel precedente articolo MooTools: usare Events e Options.
Vediamo brevemente il compito che ognuna di queste classi svolge.
La classe Fx.Style (che verrà rinominata in Fx.Tween nella prossima versione) viene utilizzata per effettuare il "tweening" sul valore di una proprietà CSS, partendo da un valore iniziale fornito dall'utente oppure calcolato automaticamente e arrivando ad un valore finale:
var fx = new Fx.Style('myElement', 'height', {duration:1400});
// azioniamo l'effetto
fx.start(600);
La classe Fx.Styles (che diventerà Fx.Morph) svolge un compito simile a Fx.Style, con la differenza che può cambiare contemporaneamente il valore di un numero qualsiasi di proprietà CSS:
var fx = new Fx.Styles('myElement', {transition:Fx.Transition.Bounce.easeOut});
// azioniamo l'effetto
fx.start({
'width': [300, 400],
'height': 600,
'color': ['#FFOOFF', '#FFFFFF']
});
La classe Fx.Slide permette di effettuare lo "slide" orizzontale o verticale di un elemento facendolo scomparire oppure apparire:
var fx = new Fx.Slide('myElement', {duration: 1000});
// azioniamo l'effetto
fx.slideIn();
Fx.Slide aggiunge un'altra opzione a quelle che eredita da Fx.Base: 'mode', che rappresenta la modalità dello slide e può assumere come valori 'horizontal' o 'vertical'.
La classe Fx.Scroll permette, nel dialetto informatico, di "scrollare" un elemento che possiede un overflow fino alle coordinate x e y stabilite. Come esempio, all'interno di moo.rd utilizzo le funzionalità di Fx.Scroll in modo da creare lo SmoothScrolling (demo).
Infine, la classe Fx.Elements, consente di applicare ad un qualsiasi numero di elementi un cambio del valore di un qualsiasi numero di proprietà CSS. Ad esempio:
var fx = new Fx.Elements($$('#myElement img'));
fx.start({
'0': { // cambio del valore delle proprietà 'height' e 'width' della prima immagine
'height': [0,1],
'width': [100,200]
},
'4': { // cambio del valore della proprietà 'opacity' della quinta immagine
'opacity': [0.2, 0.5]
}
});
Per osservare un esempio pratico, ecco la classe Kwick.Menu (demo) di moo.rd che eredita da Fx.Elements ed utilizza le sue funzionalità per applicare un cambio dei valori CSS sugli elementi di una lista.
Primo esempio: Fx.Images
Ora che sappiamo quali costrutti di effetti MooTools ci mette a disposizione e conosciamo il loro comportamento principale, possiamo passare alla creazione della nostra applicazione pratica: un esempio avanzato che permette di creare un immagine nel centro di una pagina quando si clicca sulla rispettiva thumbnail. La nostra immagine creata avrà le seguenti caratteristiche:
- apparirà nel centro della pagina al di sopra di un overlay opaco che copre tutti gli altri elementi in modo da renderla modale;
- potrà avere una didascalia ricavata dall'attributo "
alt
" della rispettiva thumbnail; - apparirà con un Fx.Style che crea un effetto fade;
- scomparirà quando l'utente clicca su di essa sempre con un effetto fade.
Per la creazione di questo esempio, oltre agli effetti e agli immancabili file delle sezioni CORE e CLASS, occorre utilizzare anche la maggior parte delle funzioni del DOM di MooTools, che tratteremo dettagliatamente nei prossimi articoli.
Vediamolo subito in azione.
Spiegazione dell'esempio
Per prima cosa creiamo una nuova classe chiamata Fx.Images (il nome è puramente inventato) che estende Fx.Style e alla quale è possibile passare un parametro che rappresenta la collezione di immagini su cui viene applicato l'effetto (se non viene specificato vengono prese di default tutte le immagini della pagina).
Inizializziamo le proprietà che ci occorreranno. Si tratta di quattro array differenti che terranno traccia delle immagini e degli effetti:
- images - sono le immagini sulla quale applicare gli effetti (di default tutte le immagini della pagina) ;
- preload - sono i preload delle immagini;
- fx - gli effetti da applicare a ciascuna immagine;
- element - gli elementi che conterranno le immagini e le didscalie e che verranno posizionati nel centro della pagina come una sorta di diapositiva.
Sempre nell'inizializzazione richiamiamo i metodi overlay
e page
in modo da creare le sezioni che copriranno gli altri elementi creando un tocco stilistico e rendendo le nostre immagini modali (sono gli stessi metodi che utilizzo nelle classi Virtual.Box e Virtual.Ajax di moo.rd). Per ogni immagine della nostra collezione creiamo l'elemento "diapositiva" che le contiene, l'immagine preload e assegniamo gli eventi che faranno la apparire e scomparire. Ecco l'initialize della nostra Fx.Images:
initialize: function(images) {
this.images = images || $$('#images img');
this.preload = [];
this.element = [];
this.fx = [];
this.overlay();
this.page();
this.images.each(function(img, i) {
this.element[i] = new Element('div', {
'id': 'mainImage'
});
this.element[i].addEvent('click', this.remove.bind(this, i));
this.fx[i] = this.element[i].effect('opacity', {duration:1500, wait:false});
img.addEvent('click', this.mechanize.bind(this, [img, i]));
this.preload[i] = new Image();
this.preload[i].src = img.src.replace('.jpg', '_big.jpg');
this.preload[i].alt = img.alt;
}, this);
if(this.options.initialize) this.options.initialize.call(this);
}
Passiamo ora all'analisi dei metodi principali che ho apportato a Fx.Images, in sostanza sono due: mechanize
e remove
. Il primo si occupa della creazione delle gerarchie da inserire nelle pagine e di definire gli stili di ciascuna sezione. Il secondo permette di rimuovere/nascondere tutto ciò che mechanize
ha creato quando l'utente clicca sull'immagine:
mechanize: function(img, i) {
this.element[i].setStyles({
'position': 'absolute',
'top': '50%',
'left': '50%',
'padding': '4px',
'background-color': '#FFFFFF',
'opacity': 0,
//'height': this.ok.height,
'width': this.preload[i].width,
'margin-top': - this.preload[i].height/2,
'margin-left': - this.preload[i].width/2
});
this.preload[i].inject(this.element[i]);
new Element('p').setHTML(this.preload[i].getProperty('alt')).inject(this.element[i]);
this.element[i].inject(this.page);
this.overlay.setStyle('display', 'block');
this.page.setStyle('display', 'block');
this.overlay.inject($E('body'));
this.page.inject($E('body'));
this.fx[i].start(1);
},
remove: function(i) {
this.fx.each(function(fx) {
fx.stop();
}, this);
this.fx[i].start(0).chain(function() {
this.element[i].empty();
this.overlay.setStyle('display', 'none');
this.page.setStyle('display', 'none');
}.bind(this));
}
Ricordo ancora che, se l'immagine ha un attributo "alt
", questo verrà utilizzato per comporre la descrizione dell'immagine.
Questo esempio è adattato per lavorare con sole immagini di tipo .jpg. Inoltre, le immagini devono seguire la seguente regola: quelle di dimensioni reali devono chiamarsi con il nome della rispettiva thumbnail seguito dal suffisso "_big". Ad esempio, se la thumbnail si chiama "alberi.jpg", la rispettiva immagine in grande dovrà chiamarsi "alberi_big.jpg". Questa è una convenzione creata per questo esempio e può essere ovviamente modificata a piacimento.
Per utilizzare le funzionalità di Fx.Images è solamente necessario creare un'istanza al caricamento della pagina:
window.addEvent('domready', function() {
// applica l'effetto a tutte le immagini della pagina
var fx = new Fx.Images();
// applica l'effetto solamente alle immagini presenti all'interno dell'elemento 'myElement'
// var fx = new Fx.Images($$('#myElement img'));
});
e la nostra applicazione funzionerà correttamente. Fx.Images mostra come sia possibile creare un effetto personalizzato sfruttando tutta la flessibilità dei costruttori Fx per gli effetti di MooTools.
Secondo esempio: Fx.Styles
Ora che abbiamo visto come creare un effetto totalmente personalizzato, vediamo come utilizzare le potenzialità di una classe che MooTools ci offre nativamente: Fx.Styles (http://docs.mootools.net/Effects/Fx-Styles.js). Come ho detto in precedenza, Fx.Styles permette di cambiare contemporaneamente il valore di un numero qualsiasi di proprietà CSS. Utilizzeremo le sue funzionalità in combinazione con il metodo chain
per creare effetti a catena.
Ecco l'esempio in azione.
Viene dichiarata un'istanza di Fx.Styles e viene richiamato il metodo start
più volte ogni volta con proprietà CSS e valori differenti:
var fx = new Fx.Styles('box', {duration:2500});
$('ok').addEvent('click', function(event) {
var event = new Event(event).stop();
fx.start({
'width': 560,
'height': 310,
'background-color': '#FFCC00',
'color': '#00CCCC',
'font-size': 22
}).chain(function() {
this.start({
'width': 260,
'height': 120,
'background-color': '#FF0000',
'color': '#FFFFFF',
'font-size': 16,
'margin-left': 100
});
}).chain(function() {
this.start({
'width': 420,
'height': 220,
'background-color': '#CCCCCC',
'color': '#FFFF00',
'font-size': 24,
'margin-left': 0,
'margin-top': 40
});
}).chain(function() {
this.start({
'width': 260,
'height': 120,
'background-color': '#FF00CC',
'color': '#0000FF',
'font-size': 14,
'margin-top': 0
});
});
});
Conclusione
In questo articolo abbiamo studiato tutte le potenti classi di effetti che MooTools ci mette a disposizione e, utilizzando le loro funzionalità, abbiamo creato un effetto totalmente personalizzato da utilizzare in applicazioni di nuova generazione. Abbiamo visto inoltre un esempio che mostra come sfruttare le potenzialità di Fx.Styles combinate con la chainabilty.
Nei prossimi articoli dedicati agli effetti vedremo come utilizzare altri costrutti importanti che ho presentato in questo articolo, come Fx.Elements, Fx.Scroll e Fx.Slide. Gli esempi visti sono disponibili per il download.