Création d’un diaporama Silverlight

Silverlight 1 est le lecteur proposé par Microsoft permettant d’afficher du contenu riche et interactif pour le Web. Un certain nombre de points communs peuvent servir de repères aux personnes désirant évoluer dans les deux environnements que sont Flash et Silverlight. L’objectif est de comprendre les mécanismes simples permettant de charger du contenu externe au sein de Silverlight. Nous verrons d’ailleurs que les méthodes pour y arriver bien que différentes, sont plus proche des principes proposés par ActionScript 3 que par ceux proposés par ActionScript 1.


Niveau requis : Notions de programmation Javascript / connaissance des bases de Silverlight 1.0 et de Expression Blend

Auteur : Eric Ambrosi

Thèmes abordés : L’objet downloader, récupération de références à des objets Xaml, librairie tweened

Logiciels et fichiers à télécharger :

- Un éditeur de votre choix pour Javascript, par exemple Aptana (ou VisualStudio 2008)

- Expression Blend 2 December , .Net 3.5

- Le plugin Silverlight pour Firefox ou l’ActiveX pour IE

- La librairie Tweened accessible ici

Récupération de l’interface Diaporama



  • Créez un nouveau “site Silverlight Javascript” au sein de Expression Blend 2 December, nommez-le diaporama par exemple. Blend 2 crée automatiquement l’arborescence ainsi que les fichiers nécessaires.

Dans un premier temps, nous allons nous concentrer sur l’interface, cependant, afin de ne pas être trop exhaustif ou ennuyant, je vous propose de récupérer le fichier Page.xaml décrivant notre interface. Par le terme “décrivant” je fais référence au langage déclaratif Xaml. Pour résumer, tout ce que l’on peut faire dans l’interface de Blend en terme de dessin vectoriel est directement traduit dans le fichier Page.xaml sous forme de Xaml.

  • Le fichier à insérer dans votre projet est ici sous forme de fichier zip.
  • Les images du diaporama sont ici , mais vous pouvez également décidez de créer votre propre répertoire “images” dans votre projet Silverlight “diaporama”.

Remarque : Si vous souhaitez de plus amples explications sur le Xaml, un tuto vidéo est accessible ici.

  • Une fois que vous l’avez récupéré, copier le fichier Page.xaml dans votre répertoire et écrasez l’ancien fichier. Voici ce que vous devriez obtenir dans Blend 2 :

Interface diaporama

Description de l’interface


L’interface est constituée de plusieurs éléments majeurs :

  • Le composant Image a l’arrière plan permet d’afficher les images.
  • Un composant conteneur Canvas “barre” permet quant à lui de contenir l’ensemble des boutons permettant de naviguer au sein des images. Comme vous pouvez le constater, Canvas est un peu l’homme à tout faire dans Silverlight, il sert à la fois de conteneur mais également d’élémént interactif. On peut le comparer jusqu’à un certain point au MovieClip de Flash :). Pour cela, tous les boutons présents dans le Canvas “barre” sont également des Canvas. Ceux-ci contiennent des tracés ou des primitives vectorielles.
  • Au sein du conteneur barre, nous avons les deux éléments qui vont nous indiquer la progression du téléchargement en cours. L’un s’appelle “progressText”, l’autre “progressbarre”.
  • Les boutons quant à eux ne font pas référence à des animations pour le moment. Nous leur en donnerons grâce à la librairie Tweened.

Le code [behind] javascript

Ce que j’appelle le code behind est en fait le code logique de notre application, ce n’est donc pas le code qui décrit l’interface mais plutôt le code qui nous permet d’interagir avec les objets Xaml et de leur affecter des comportements utilisateurs. Au sein de Silverlight, c’est le fichier Page.xaml.js qui contient ce code. Nous avons donc bien affaire à du javascript.

Ouvrez ce fichier, de base vous devriez avoir une méthode handleLoad, celle-ci se déclenche lorsque l’application est chargée.

Accrochez-vous voici le code :

if (!window.diaporama)
    window.diaporama = {};
 
diaporama.Page = function()
{
}
 
diaporama.Page.prototype =
{
handleLoad: function(control, userContext, rootElement)
    {
        this.control = control;
 
        //création du downloader
        //le downloader ne peut-être créé que lors du chargement complet
        //de l'application Silverlight
        //Il diffuse 3 événements mais seulement 2 nous interessent
            //le premier est diffusé lorsque le chargement est en cours
            //le second est diffusé lorsque le chargement est terminé
        this.myDownloader = this.control.createObject("downloader");
        this.myDownloader.addEventListener("downloadProgressChanged", Silverlight.createDelegate(this,this.onProgress));
        this.myDownloader.addEventListener("completed", Silverlight.createDelegate(this,this.onComplete));
        //j'initialise une variable sur this permettant de charger la première image
        this.num = 0;
        //je crée à la main mon tableau d'images :)
        //mais vous pourriez à ce stade récupérer du Xml via Php avec XMLHttpRequest
        this.imageTab = ["images/ratatouille0.jpg","images/ratatouille1.jpg","images/ratatouille2.jpg","images/ratatouille3.jpg"];
 
        //on initialise le downloader pour charger la première image du tableau
         this.myDownloader.open("GET", this.imageTab[this.num] );
        //Une fois que la cible est déterminée, on déclenche le téléchargement avec la méthode send()
        this.myDownloader.send();
 
        //Voilà le point interessant :
        //La méthode findname de l'objet rootElement(Canvas racine Page dans Blend 2)
        //permet de facilement récupérer des références d'objets Xaml
        var lire_button = rootElement.findName('lire_button');
        var stop_button = rootElement.findName('stop_button');
        var avance_button = rootElement.findName('avance_button');
        var arriere_button = rootElement.findName('arriere_button');
 
        //je stocke certaines références dans this afin de pouvoir y faire appel par la suite
        this.imageContainer = rootElement.findName('imageContainer');
        this.titreImage = rootElement.findName('titreImage');
        this.titreImage.Visibility = 'Collapsed';// je rends invisible cet objet
        this.progressBarre = rootElement.findName('progressBarre');
        this.progressBarre.Visibility = 'Collapsed';// je rends invisible cet objet
        this.progressText = rootElement.findName('progressText');
        this.progressText.Visibility = 'Collapsed';// je rends invisible cet objet
 
        //On déclare ici des fonctions déclenchée lorsque l'on clique ceux-ci
        avance_button.addEventListener("MouseLeftButtonDown", Silverlight.createDelegate(this, this.forwardShow));
        arriere_button.addEventListener("MouseLeftButtonDown", Silverlight.createDelegate(this, this.backwardShow));
        lire_button.addEventListener("MouseLeftButtonDown", Silverlight.createDelegate(this, this.lireDiapo));
        stop_button.addEventListener("MouseLeftButtonDown", Silverlight.createDelegate(this, this.stopDiapo));
 
        //pour finir j'utilise la librairie Tweened.org pour permettre de créer simplement un effet de transition
        //param 1 : l'objet Xaml à animer - param 2 : un tableau de propriétés 1 seule le plus souvent - param 3 : le type d'équation
        //param 4 : la durée en seconde - param 5 : la valeur finale de la propriété
        //param 5 facultatif : la valeur initiale de la propriété
        var monObjectTweened = new TweenObject(this.imageContainer,["opacity"],"linear",0.5,0,1);
        //Vous pouvez maintenant créer le nouveau Tween en passant l'objet en paramêtre
        this.opacTween = new Tween(monObjectTweened);
        this.opacTween.typeTween();//ici je trace dans firefox avec firebug l'ensemble des équations possibles
        //Pour finir, je déclenche une fonction lorsque le tween est fini qui permet de charger l'image suivante ou précédente
        this.opacTween.onComplete = Silverlight.createDelegate(this,this.initCharge);
 
    }
 
/* ... */
 
}

Les méthodes de navigation

  • Les 2 premières sont les méthodes déclenchées lorsqu’un clic sur les boutons avant et arriere est diffusé.
  • Les 2dernière permettent simplement de gérer la lecture automatique de images.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// fonction déclenchée lorsqu'on clique sur le bouton arriere     
backwardShow: function(sender, eventArgs, pNum)     {         
	//on affecte la nouvelle valeur reçue à this.num pour rester dans des valeurs corrects         
	this.num = Math.max(0,--this.num);         
	//on définit l'url du fichier à ouvrir et la méthode         
	this.myDownloader.open("GET", this.imageTab[this.num] );          
	//initialisation du Chargement, lorsque le opacTween est fini          
	//il exécute la méthode initCharge         
	this.opacTween.start();     
}, 
 
// fonction déclenchée lorsqu'on clique sur le bouton avant     
forwardShow: function(sender, eventArgs)     {         
	//on affecte la nouvelle valeur reçue à this.num pour rester dans des valeurs corrects         
	this.num = (++this.num)%this.imageTab.length;         
	//on définit l'url du fichier à ouvrir et la méthode         
	this.myDownloader.open("GET", this.imageTab[this.num] );         
	//initialisation du Chargement, lorsque le opacTween est fini         
	//il exécute la méthode initCharge         
	this.opacTween.start();     
},
 
//fonction qui crée une lecture automatique     
lireDiapo: function(sender, eventArgs)     {         
	 //la fonction globale setInterval me permet ici de répéter automatiquement         
	 //le chargement de l'image toutes le 5 secondes :)         
	 this.intervalLecture = setInterval(Silverlight.createDelegate(this, this.forwardShow), 5000);     
},   
 
//fonction qui stoppe la lecture automatique     
stopDiapo: function(sender, eventArgs)     {         
	 //je supprime la répétition         
	 clearInterval(this.intervalLecture);     
},

Les méthodes de gestion du chargement

Il ne faut pas oublier que l’objet downloader diffuse des événements par lui-même, le paramêtre sender est une réference faible de cet objet.

  • le onComplete est déclenché lorsque l’image est chargée.
  • le onProgress est déclenché lorsque le téléchargement est en cours.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// fonction déclenchée lorsque le chargement d'une image est terminé     
onComplete: function(sender, eventArgs)     {         
	 //sender représente ici le diffuseur de l'évènement, il s'agit donc du downloader         
	 //la méthode setSource du composant image nous permet d'afficher l'image contenu         
	 //dans l'objet downloader         
	 this.imageContainer.setSource(sender,"");         
	 //on cache les éléments indiquant la progression du téléchargement         
	 this.progressText.Visibility = 'Collapsed';         
	 this.progressBarre.Visibility = 'Collapsed';         
	 //on affiche le titre de l'image chargée         
	 this.titreImage.Visibility = 'Visible';         
	 this.titreImage.text = this.imageTab[this.num];         
	 //on demande au tween opacTween de démarrer une animation inverse         
	 //c'est pratique car notre image était invisible avec une opacité de 0         
	 //là le tween.reverse nous permet de revenir à une opacité de 1 :)         
	 //sans dépenser de sueur         
	 this.opacTween.reverse();     
},  
 
// fonction déclenchée lorsque le chargement est en cours     
onProgress: function(sender, eventArgs)     {        
	 //sender représente ici le diffuseur de l'évènement, il s'agit donc du downloader        
	 //la valeur du téléchargement en cours est contenue et mise à jour dans la propriété        
	 //downloadProgress. Cette valeur débute à 0 pour arriver à 1        
	 this.progressBarre.width = sender.downloadProgress*460;        
	 //je suis oligé d'arrondir afin d'avoir un pourcentage entier :)        
	 this.progressText.text = (Math.round(sender.downloadProgress * 100)) + " %";     
}, 
 
initCharge: function ( )     {         
	 //on déclenche le téléchargement grâce à la méthode send :)         
	 this.myDownloader.send();         
	 //on cache le titre de la précédente image         
	 this.titreImage.Visibility = 'Collapsed';         
	 //on rend visible les indicateurs de progression :)         
	 this.progressText.Visibility = 'Visible';         
	 this.progressBarre.Visibility = 'Visible';     
}

Conclusion

Les sources de ce tuto sont téléchargeables ici . Vous devriez pouvoir le faire fonctionner sans trop de problème :). Il suffit simplement de le dézipper sur votre disque et de le lancer avec Aptana par exemple, n’oubliez cependant pas de définir default.html comme startPage et installez tout ce donc vous avez besoin pour lire et travailler avec Silverlight auparavant.

Pour finir, l’objet downloader connait une méthode qui est déclenchée lorsque le contenu n’est pas correctement chargé. De plus il permet par exemple de télécharger un fichier zip puis de naviguer directement en son sein. Il a de multiples autres applications, par exemple, charger des Javascripts, de la vidéo ou des fichiers Xaml. On pourrait en dire beaucoup plus mais globalement les principes ci-dessus sont les plus importants.

Répondre