Dot.Blog

C#, XAML, Xamarin, UWP/Android/iOS

Silverlight 3 : un Behavior ajoutant un effet de reflexion (avec les nouvelles WriteableBitmap)

Dans le précédent billet je vous proposais d'écrire un Behavior effectuant une rotation animée d'un élément visuel, aujourd'hui je vous invite à la réflexion...

Je veux parler de l'effet de réflexion tant à la mode. WPF sait parfaitement le faire grâce notamment au brosses visuelles qui permettent facilement de "peindre" un contrôle avec la copie visuelle d'un autre objet (ou arbre d'objets). Hélas, Silverlight 3 ne possède pas encore de brosse de ce type et pour obtenir l'effet désiré il faut dupliquer le ou les objets sources et leur faire subir une rotation, un flip, et l'ajout d'un masque d'opacité. Tout cela est assez fastidieux il faut bien l'avouer.

Mais grâce aux Behaviors il est possible de rendre tout cela automatique et avec l'aide des WritableBitmap il n'est même pas nécessaire de dupliquer tous les objets !

J'ai déjà détaillé dans le billet précédent la technique de création d'un Behavior, je vous renvoie ainsi à cet exemple pour la base. Pour l'effet de réflexion, le mieux est de regarder ci-dessous l'exemple live :

[silverlight:source=/SLSamples/Reflection/ReflectionBehavior.xap;width=424;height=294]

Pour créer cet effet nous allons utiliser une nouvelle classe de Silverlight 3 : les WritableBitmap. Cette classe permet de créer des images de toute pièce ce qui n'était pas possible jusqu'à lors.

Non seulement les WritableBitmap permettent de créer une bitmap par code, mais en plus elle possède une méthode de Render qui est capable de faire le rendu de tout objet ou arbre visuel et de le placer dans la bitmap. Nous allons utiliser cette possibilité pour remplir une bitmap à laquelle nous appliquons ensuite quelques transformations (renversement, échange gauche/droite, translation). Un masque d'opacité est ajouté pour l'impression de dégradé d'opacité.

Le Behavior fonctionne sur des sources de type Canvas uniquement, cela permet d'illustrer comment limiter un Behavior à une classe ou une branche de classes donnée. Une fois l'image du reflet créé elle est ajoutée en tant qu'élément au canvas (après avoir pris soin de supprimer la précédente image s'il y en a déjà une).

Le Behavior n'a pas de rendu en mode design sous Blend 3, c'est un petit défaut. De même l'effet de réflexion est créé une fois pour toute et n'est modifié que si le canvas source voit sa taille changée. Si vous créez dynamiquement des objets sur celui-ci, le reflet ne changera pas. Bien entendu on pourrait penser connecter le Behavior à l'événement de rendu du canvas LayoutUpdated. Cela eut été une solution élégante. Hélas on créerait une boucle infinie puisque notre Behavior ajoute un objet au canvas ce qui déclenche le renouvellement de son rendu. On pourrait améliorer les choses en ne faisant pas le rendu dans le canvas source et en ajoutant une propriété au Behavior qui serait un objet de type Image (non enfant de la source) qu'on utiliserait comme sortie de rendu de l'effet de reflet. Mais cela poserait d'autres problèmes. 

Toutes les idées sont envisageables et le code proposé n'est qu'un exemple. A vous de l'améliorer sans oublier de venir ici nous dire ce que vous avez fait !

Côté paramétrage le Behavior permet de modifier les points de départ et d'arrivée du dégradé du masque d'opacité ainsi que l'offset sur l'axe Y. Sans ce dernier le reflet serait collé au canvas source ce qui n'est pas forcément très beau. Par défaut un décalage de 3 pixels vers le bas décolle légèrement le reflet de l'original.

Code la publication d'un code un peu long n'est pas forcément très lisible sur le blog, je vous renvoie au code source du projet complet que vous n'avez plus qu'à télécharger ici : ReflectionBehavior.zip (62,91 kb)

Et Stay Tuned !

 

blog comments powered by Disqus