Animations FireMonkey - John COLIBRI. |
- résumé : les animations FireMonkey Delphi XE2 : choix de la propriété à animer, vitesse, type d'interpolation entre les valeurs début et fin, répétition - Animation 3D
- mots clé : tAnimation.PropertyName - tFloatAnimation - tInterPolation - tAnimationType - Loop - Trigger et TrigerInverse
- logiciel utilisé : Windows XP personnel, Delphi XE2
- matériel utilisé : Pentium 2.800 Mhz, 512 Meg de mémoire, 250 Giga disque dur
- champ d'application : Delphi XE2 FireMonkey
- niveau : développeur Delphi
- plan :
1 - Les Animations FireMonkey Delphi XE2 FireMonkey est la nouvelle librairie Delphi XE2 qui affiche graphiquement les contrôles visuels (boutons, edits etc) avec la possibilité de créer, en Win32,
des applications pour Windows 32 et 64, Mac OsX et iOs (iPhone, iPad etc) Nous avons déjà présenté les Styles FireMonkey,
en insistant que ces styles sont bien plus qu'un habillage visuel comme des skins ou des thèmes. Les styles FireMonkey sont au coeur de la représentation graphique des contrôles multi-plateforme. Un contrôle est composés de plusieurs
éléments (par exemple, pour un tButton, un tLayout, un tRectangle, un tText et ... des tAnimations). Voici les éléments d'un simple bouton:
Les Animation permettent de modifier les paramètres de position des contrôles à l'écran (X, Y, rotation, échelle ...), ainsi que les couleurs.
2 - La première animation FireMonkey La première Animation FireMonkey 2.1 - Déplacer un tButton à l'écran Pour animer la position X d'un tButton
| lancez Delphi XE2 |
| créez une application FireMonkey 2D par |
| dans la Tool Palette, sélectionnez un tButton et posez le sur la Forme | |
de l'onglet "Animations" de la Tool Palette, sélectionnez "Animations | tFloatAnimation" |
| cliquez sur Button1 pour poser cette tFloatAnimation SUR Button1. | |
la FloatAnimation1 n'est pas représentée sur la Forme, mais elle apparaît comme un élément fils de Button1 dans le paneau Structure, en haut à gauche: Si Button1 n'était pas séléctionné lorsque vous déposez FloatAnimation, l'animation sera un fils de la Forme, et c'est celle ci qui sera animée. Dans ce cas:
| sélectionnez FloatAnimation1 dans le paneau de structure et tirez-glissez la SUR Button1 | |
Nous modifions à présent les propriétés de FloatAnimation dans l'Inspecteur d'Objet:
Pour déplacer Button1 horizontalement avec des aller-retours: | sélectionnez PropertyName |
| l'Inspecteur d'Objet présente toutes les propriétés de Button1 que FloatAnimation peut modifier: | | sélectionnez Position.X |
| sélectionnez la position maximale qui déterminera quand le déplacement s'arrêtera, par exemple 200 | |
cliquez Loop pour répéter l'animation | | cliquez Enabled pour lancer l'animation dès le lancement de l'.EXE |
| compilez et exécutez | |
Button1 se déplace de la position 0 (StartValue, valeur par défaut) à 200 | Notez que - les positions des contrôles sont définies par Position.X et Position.Y
(et non plus par Left et Top), qui sont des réels pour conserver la précision lors des transformations graphiques
- c'est pourquoi nous avons utilisé un tFloatAnimation
- nous avons ajouté l'événement FloatAnimation1.OnProcess qui permet d'afficher la position du bouton à chaque itération
- nous avons aussi ralenti la vitesse en donnant à FloatAnimation1.Duration
la valeur 2, puis 10
Pour effectuer une animation, les propriétés nécessaires sont - le contrôle dont l'animation est le fils. Attention, par défaut, le "drag
and drop" depuis la Tool Palette posera l'animation sur la Forme. Il faudra alors utiliser le Structure Pane pour nicher l'animation dans son contrôle parent. Le mieux est d'utiliser le "clic sur la Tool Panel, clac sur le contrôle parent"
- PropertyName : c'est la valeur qui sera modifiée de l'animation. Nous avons utilisé Button1.Position.X. Nous aurions pu prendre Y, ou Width. Et
pour effectuer des animations en 2D ou plus, il faut déposer autant de composants animation que de valeurs à animer. Pour déplacer notre bouton horizontalement et verticalement en l'élargissant, il aurait fallu ajouter 2 autres tFloatAnimation
- des valeurs initiales et finales, qui sont gouvernées par StartValue, StopValue et / ou StartFromCurrent
Voyons à présent les principales propriétés de tFloatAnimation
2.2 - tFloatAnimation.Inverse Dans notre cas, Button1 va de StartValue (0) vers StopValue (200). Si nous basculons Inverse à True, le bouton se déplace de 200 vers 0
2.3 - tFloatAnimation.Enabled, StartValue, StopValue
Le basculement de Enabled à False, arrête l'animation ET donne à la position la valeur de StopValue (100 dans notre figure) . Le redémarrage se fait par le
basculement de Enabled à True, et la valeur de la position redémarre à StartValue
Si nous basculons StartFromCurrent, l'animation démarre à partir de Button1.Position.X:
au lieu de commencer à Startvalue :
Notez :
- il y a un léger décalage entre les positions de démarrage de l'animation et l'affichage, mais cela est peut être du au moment où OnProcess est appelé
2.4 - Enabled, Start(), Stop()
La propriété Enabled permet de lancer ou arrêter les animations. Start() et Stop() sont les méthodes sous-jacentes
2.5 - Duration et Delay
Duration spécifie la durée (en secondes) pour aller de StartValue à StopValue. Cette propriété permet donc de régler la vitesse de l'animation Delay permet de retarder le démarrage de l'animation
2.6 - Interpolation et AnimationType L'animation permet donc de faire varier une propriété en fonction du temps. La loi de changement peut être de plusieurs natures - linéaire
- exponentielle
- sinusoidale
- élastique
C'est la propriété Interpolation qui détermine cette loi. Pour les lois qui ne sont pas symmétriques, c'est AnimationType qui indique dans quel sens la loi est exécutée. Prenons le cas d'une animation élastique
(semblable à une sinusoide amortie). Nous pouvons avoir les grandes oscillations au début ou à la fin. Ce qui correspond aux différentes valeurs de AnimationType - atIn débute par une faible oscillation qui croît
- atOut débute par une grande oscillation qui s'amenuise
- atInOut débute par une petite oscillation, puis un mouvement ample au milieu, et un decrescendo vers la fin
Pour se rendre compte de ces possibilités, voici une application où nous pouvons choisir les valeurs de Interpolation et AnimationType. Pour cela nous allons animer les valeurs X et Y d'un tRectangle
- en conservant une loi linéaire pour X
- en choisissant dans deux tListBox la loi et le sens de Y
Le mouvement sera donc uniforme de la gauche vers la droite, mais uniforme, ou exponentiel ou sinusoidal etc en Y.
Voici l'application : | créez une nouvelle application FireMonkey | |
posez deux tListBox sur le Forme | | posez un tButton sur la Forme et initialisez par code le contenu de ces
tListBox avec les valeurs possibles de tInterpolation et tAnimationType par le clic du bouton
Uses TypInfo;
Function f_interpolation_type_name(p_interpolation_type: tInterpolationType): String;
Begin
Result:= GetEnumName(TypeInfo(TInterpolationType), Integer(p_interpolation_type));
End; // f_interpolation_type_name
Function f_animation_type_name(p_animation_type: tAnimationType): String;
Begin
Result:= GetEnumName(TypeInfo(TanimationType), Integer(p_animation_type));
End; // f_animation_type_name
Procedure TForm1.initialize_Click(Sender: TObject);
Var l_interpolation_type: tInterpolationType;
l_animation_type: tAnimationType; Begin
// -- fill the interpolation and animation type listboxes
For l_interpolation_type := Low(TInterpolationType) To High(TInterpolationType) Do
interpolation_listbox_.Items.AddObject(f_interpolation_type_name(l_interpolation_type),
TObject(l_interpolation_type));
interpolation_listbox_.ItemIndex := 0;
For l_animation_type := Low(TanimationType) To High(TanimationType) Do
animation_listbox_.Items.AddObject(f_animation_type_name(l_animation_type),
TObject(l_animation_type));
animation_listbox_.ItemIndex := 0; End; // initialize_CLick |
| | de l'onglet Shape, posez un tRectangle sur la Forme |
| de l'onglet Animation, sélectionnez un tFloatAnimation et cliquez sur Rectangle1 pour la poser sur ce rectangle. Faites de même pour la second animation |
| pour varier, initialisez ces deux animation par code (il serait possible de tout définir dans l'Inspecteur d'Objet)
Procedure TForm1.initialize_Click(Sender: TObject);
Begin ooo
// -- Attach the FloatAnimations to the Rectangle's position
With FloatAnimation1 Do Begin
Parent := Rectangle1; // already done
PropertyName := 'Position.X';
StartValue:= Rectangle1.Position.X;
StopValue := Rectangle1.Position.X + 200;
Duration := 5;
AnimationType := tAnimationType.atIn;
Interpolation := tInterpolationType.itLinear; End;
With FloatAnimation2 Do Begin
Parent := Rectangle1;
PropertyName := 'Position.Y';
StartValue:= Rectangle1.Position.Y;
StopValue := Rectangle1.Position.Y - 200;
Duration := 5;
AnimationType := tAnimationType.atIn;
Interpolation := tInterpolationType.itLinear; End;
End; // initialize_CLick | | |
posez un bouton "animate_" qui va démarrer les animations, avec les valeurs sélectionnées dans les listbox:
Procedure TForm1.move_Click(Sender: TObject);
Var l_animation_type: TAnimationType;
l_interpolation_type: TInterpolationType; Begin
With animation_listbox_ Do
l_animation_type := TAnimationType(Integer(Items.Objects[ItemIndex]));
FloatAnimation2.AnimationType := l_animation_type;
With interpolation_listbox_ Do
l_interpolation_type := TInterpolationType(Integer(Items.Objects[ItemIndex]));
FloatAnimation2.Interpolation := l_interpolation_type;
FloatAnimation1.Start; FloatAnimation2.Start;
End; // move_Click | | |
compilez et exécutez | | cliquez "initialize_" pour remplir les deux listbox |
| sélectionnez par exemple "itElastic" et "atIn" | | cliquez "animate_" |
| le rectangle se déplace vers la droite en oscillant de plus en plus fort verticalement |
| sélectionnez "atOut" | | le rectangle oscille fortement verticalement, et ces oscillations diminuent |
Notez que
- expliquer des animations par du texte et des images statiques relève du paradoxe.
- le mieux serait de dessiner la trajectoire suivi par le tRectangle. Nous n'y sommes pas arrivés
- l'aide Delphi, dont est tiré cet exemple, contient des notations erronnées (les énumérés d'interpolation correspondent à des identificateurs de la beta test avant des changements de noms effectués mi Août)
- le code pour tracer devrait utiliser:
- l'initialisation de la brosse employée pour tirer les traits
Canvas.Stroke.Color := tAlphaColor.Red;
Canvas.Stroke.Kind:= tBrushKind.bkSolid; |
- le tracé entre la position courante et la position précédente dans l'événement OnProcess de l'une des animations :
Var g_previous_position: tPointF;
Procedure TForm1.FloatAnimation1Process(Sender: TObject);
Var l_current_position: tPointF; Begin
l_current_position.X := Rectangle1.Position.X;
l_current_position.Y := Rectangle1.Position.Y;
Canvas.DrawLine(l_current_position, g_previous_position, 1.0);
g_pevious_position:= l_current_position; End; // FloatAnimation1Process
| Nous n'avons jamais pu le faire fonctionner. De plus, la moindre faute de syntaxe a zappé Delphi XE2. Nous l'avons rechargé une cinquantaine de fois,
sans amélioration. Il est probable que nous avons un problème de hard sur ce PC que nous utilisons depuis début Septembre. Ou alors nous avons réussi a "animer le crash de XE2" !
- l'exemple sans tracé de la trajectoire fonctionne néanmoins
Plus intéressant, notez - la notation totalement qualifiée des énumérés, que nous avions déjà rencontré dans notre article sur les styles:
- tInterpolation est défini dans FMX.TYPES par:
Type TInterpolationType = (itLinear, itQuadratic, itCubic,
itQuartic, itQuintic, itSinusoidal, itExponential, itCircular,
itElastic, itBack, itBounce | - pour attribuer une valeur, nous utilisons
FloatAnimation1.Interpolation := tInterpolationType.itLinear; |
- le changement des propriétés par rapport à la VCL (Fill et Stroke pour le dessin, Position pour la position etc)
- le changement des unités (tBrush se trouve dans FMX.TYPES, et pas dans GRAPHICS)
2.7 - Trigger et TriggerInverse Ces propriétés permettent de démarrer une animation en fonction d'un événement. Par exemple lorsque la souris arrive au dessus d'un contrôle (
Voici un exemple qui agrandit un tEdit lorsque la souris arrive au dessus du contrôle, et le rétrécit lorsqu'il sort:
Nous pouvons aussi retourner aux valeurs initiales, en utilisant InverseTrigger et la valeur inverse:
Nous aurions aussi pu utiliser une seconde tFloatAnimation pour retourner à l'état initial
Notez que
- Trigger et TriggerInverse sont des String
- les propriétés du parent qui peuvent être utilisées sont:
- IsMouseOver
- IsFocused
- IsVisible
- IsDragOver
- IsOpen.
- la chaîne se note donc, par exemple 'IsDragOver=True'
3 - Animation FireMonkey 3D Allez, un peu de chiqué pour finir:
Notez que - Les "poignées" rectangulaires servent à orienter le composant 3D. En rouge
l'une de ces poignées. La poignée cubique en bas à droite sert à dimensionner le composant (pas la lumière qui est de taille fixe)
- X va du centre de l'écran vers l'est
- notre Forme comprend aussi le texte 3d de la démo 3D de FireMonkey (avec un Y de 10 qui le rend invisible dans notre image)
4 - Vcl ou FireMonkey ? 4.1 - Stabilité
- mettez vous en "Tools | Options | Edit AutoSave", comme d'habitude, et sauvegardez vos sources fréquemment. Cave Emptor.
- actuellement, Delphi XE2 est un peu moins stable que Delphi XE. Cela devrait
être inversé avec les prochaines mises à jour
4.2 - Documentation - très générale à ce stade
- les démos sont certainement la meilleure source d'inspiration à ce stade
- ici aussi les mises à jour sont attendues avec impatience
- Embarcadéro France devrait organiser plusieurs Workshops FireMonkey. Ceux-ci devraient vous permettre une prise en main plus facile de FireMonkey
4.3 - Vcl ou FireMonkey ? - un blog très intéressant a été publié par Julian BUCKNALL de DevX. Plusieurs points en ressortent
- Embarcadero externalise de plus en plus, notamment en Espagne et en Russie
- Embarcadéro soutient que la Vcl continuera à se développer. Mais le poids respectifs du développement de chacun dépendra de nous
- néanmoins de nombreux développeurs "backend" (comptabilité, facturation)
doutent, à juste titre, que les comptables se précipitent sur leur iPhone ou même leur iPad pour effectuer leur saisie. Les applications Vcl Win32 ont donc encore de beaux jours devant elles. Quitte à ajouter un peu de "touch" ici ou là
- et ces développeurs ne se lanceront dans FireMonkey que si des composants comme QuantumGrid ou autre auront franchi le pas
- en résumé il semble qu'Embarcadéro ait fait un pari énorme sur FireMonkey.
Le développement fulgurant des mobiles les y a entraînés. Il reste à fournir une version stable et documentée de cette plateforme.
- le chef de produit Delphi a promis des mises à jour mensuelles de FireMonkey. Elles seront les bienvenues
- quoiqu'il en soit, l'effort est celui de la prise en main d'une nouvelle librairie de composants graphiques, ce qu'est bien FireMonkey. Certes les composants non visuels sont les mêmes (bases de données, Indy) etc. Mais il
y aura tout de même quelques surprise dans la migration (il faut, par exemple, qualifier le nom des unités)
- une petite critique finale: la furieuse activité de promotion mondiale de
Delphi XE2 fait chaud au coeur, mais la première manipulation déçoit un peu, surtout au niveau de la doc de FireMonkey. D'aucuns affirment qu'une présentation de FireMonkey comme une "première version" de cet outil eut été
plus réaliste et sage que comme "l'outil qui vous permettra de placer vos applications dans les mac store demain". Hem. Il est donc impératif que ce produit se consolide et se stabilise.
5 - Télécharger le code source Delphi Vous pouvez télécharger: Ce .ZIP qui comprend: - le .DPR, la forme principale, les formes annexes eventuelles
- les fichiers de paramètres (le schéma et le batch de création)
- dans chaque .ZIP, toutes les librairies nécessaires à chaque projet (chaque .ZIP est autonome)
Ces .ZIP, pour les projets en Delphi 6, contiennent des chemins RELATIFS. Par conséquent: - créez un répertoire n'importe où sur votre machine
- placez le .ZIP dans ce répertoire
- dézippez et les sous-répertoires nécessaires seront créés
- compilez et exécutez
Ces .ZIP ne modifient pas votre PC (pas de changement de la Base de Registre, de DLL ou autre). Pour supprimer le projet, effacez le répertoire.
La notation utilisée est la notation alsacienne qui consiste à préfixer les identificateurs par la zone de compilation: K_onstant, T_ype, G_lobal,
L_ocal, P_arametre, F_unction, C_lasse. Elle est présentée plus en détail dans l'article La
Notation Alsacienne
Comme d'habitude: - nous vous remercions de nous signaler toute erreur, inexactitude ou
problème de téléchargement en envoyant un e-mail à jcolibri@jcolibri.com. Les corrections qui en résulteront pourront aider les prochains lecteurs
- tous vos commentaires, remarques, questions, critiques, suggestion d'article, ou mentions d'autres sources sur le même sujet seront de même les bienvenus à jcolibri@jcolibri.com.
- plus simplement, vous pouvez taper (anonymement ou en fournissant votre e-mail pour une réponse) vos commentaires ci-dessus et nous les envoyer en cliquant "envoyer" :
- et si vous avez apprécié cet article, faites connaître notre site, ajoutez un lien dans vos listes de liens ou citez-nous dans vos
blogs ou réponses sur les messageries. C'est très simple: plus nous aurons de visiteurs et de références Google, plus nous écrirons d'articles.
6 - Quelques références
- Delphi: VCL is dead, long live FireMonkey
Julian Bucknall (DevExpress) - 19 Sept 2011
- Vcl vs FireMonkey. Très instructif
- la doc officielle
- nos précédents articles Delphi XE2 :
- Présentation Delphi XE2
John COLIBRI - 18 Août 2011
- Présentation des informations disponibles sur Delphi XE2 à partir de ce qui était publié sur le Web à cette date.
- Delphi XE2 - World Tour ParisRésumé de ce que nous avons appris à la conférence "Delphi XE2 World Tour" qui s'est
déroulée à Paris le 8 Septembre 2011 - Complément à l'article du 19 Août
- Les Styles FireMonkey : changer le style
d'un objet ou de tous les objets d'une Class, le Style Designer FireMonkey, contenu d'un fichier .STYLE, la propriété StyleLookup, les styles prédéfinis (en anglais).
- Mise à jour Delphi XE2 1 Tim DelChiaro a annoncé et fourni les liens du téléchargement et de la doc de la
première mise à jour Delphi XE2 (28 Septembre 2011).
- LiveBindings Delphi XE2 : les LiveBindings permettent d'évaluer dynamiquement des expressions entre
propriétés de composants source et cible. La définition des relations sous forme de String offre une grande flexibilité et est plus générale que les db_xxx de la VCL. Ces LiveBindings seront surtout utilisée par
FireMonkey, en particulier pour les bases de données
- Architecture LiveBindings
Delphi : analyse de l'architecture des LiveBindings Delphi : comment tBindingExpression compile une expression au format String pour contruire un environment qui référence des tObject et évalue cette
expressioin pour remplir les propriétés de composants. Affichage du pseudo-code généré. Diagramme de classe UML de l'architecture des LiveBindings
- Architecture FireMonkey : la hiérarchie tComponent <- tFmxObject <- Fmx.tControl <-
tStyledControl. Diagramme de Classe UML avec les principaux composants et explication de l'emplacements des fonctionalités de base (le Canvas, la Souris, le Clavier).
- Inspecteur d'Objet simple avec FireMonkey : création d'un Inspecteur d'Objet simple, présentant les
composants présents sur la Forme et affichant les noms et valeurs de ses propriété, avec modifications possibles des propriétés à l'exécution. Utilisation de la RTTI, version pré et post Delphi 2010
7 - L'auteur
John COLIBRI est passionné par le développement Delphi et les applications de Bases de Données. Il a écrit de nombreux livres et articles, et partage son temps entre le développement de projets (nouveaux projets, maintenance, audit, migration BDE, migration Xe_n, refactoring) pour ses clients, le
conseil (composants, architecture, test) et la
formation. Son site contient des articles
avec code source, ainsi que le programme et le calendrier des stages de formation Delphi, base de données, programmation objet, Services Web, Tcp/Ip et
UML qu'il anime personellement tous les mois, à Paris, en province ou sur site client. |