|
Télécharger le .dir correspondant à cette étape (bouton droit -> enregistrer la cible) |
Dans cette deuxième étape, nous allons fabriquer un premier ascenseur que j'appellerai rudimentaire : l'appui sur l'une des deux flèches provoque le défilement du texte de trois lignes, dans un sens ou dans un autre selon la flèche que l'on aura actionnée. Il faudra recliquer sur une flèche pour se déplacer vers les trois lignes suivantes ou précédentes... |
Pour que toutes
les conditions soient réunies, il faut qu'une autre propriété
de l'acteur champ, soit, elle, réglée à fixe.
En Lingo, cette propriété s'appelle boxType.Le
réglage de cette propriété, en général définitif,
se fait comme à l'habitude dans l'inspecteur de propriétés,
onglet champ, où l'option de cadrage sera réglée à
fixe (en lingo, cette valeur de la propriété boxType
s'appelle #fixed).
Ceci veut dire que le sprite conservera sa taille sur la scène, quelle
que soit la longueur du texte qu'il héberge.
Les autres options possibles sont :
- Redimensionnement auto (#adjust) : le sprite prendra
automatiquement la taille correpondant à la quantité de texte
à afficher. Ce n'est généralement pas le cas de ce que
nous souhaiterons, surtout avec du texte dynamique dont la longueur peut évoluer
pendant la durée de vie de l'application, ce qui posera certainement
alors de gros problèmes de mise en page.
- Défilant (en lingo #scroll) : alors le sprite
conservera la taille qui lui a été initialement assignée,
mais Director rajoutera automatiquement un ascenseur sur le bord droit du sprite.
Cet ascenseur aura l'aspect graphique des ascenseurs du système d'exploitation
sur lequel tournera l'application. C'est efficace, mais graphiquement, nous
souhaiterons sans doute avoir quelque chose de plus beau et de plus personnalisé.
- Limité à la taille du champ (en lingo #limit)
: en gros, l'effet sera le même qu'avec le redimensionnement automatique,
c'est à dire que nous rencontrerons les mêmes problèmes
de mise en page.
Pour faire bouger le texte dans la partie visible de la fenêtre, nous allons utiliser une propriété fondamentale des champs texte, laquelle s'appelle le scrollTop.
Les trois schémas
ci-dessous montrent la manière dont cette propriété fonctionne
; elle mesure en fait la distance, en pixels, qui sépare le bord haut
du sprite qui contient le texte, de la première ligne du texte.
Dans ces schémas, le rectangle jaune figure le sprite, lequel laisse
voir le texte qui s'inclue dans sa surface. Le reste du texte (partie haute
et/ou basse) est représenté en grisé. Ces parties de texte,
qui appartiennent bien à l'application, sont cachées, invisibles
pour l'utilisateur, ce qui justifie la création d'un ascenseur.
Les flèches verticales représentent la valeur du scrollTop de l'acteur champ.
|
|
|
|
| Fig. 1 : Dans cette figure, la première ligne du texte est visible en haut du sprite : le scrollTop vaut 0. | Fig. 2 : Dans cette figure-ci, une partie quelconque au milieu du texte est visible ; le scrollTop a une valeur de n pixels, positive quand le haut du texte est plus haut que le bord haut du sprite. | Fig. 3 : Dans cette dernière figure, on peut lire, au bas du sprite, la dernière ligne du texte : le scrollTop est à son maximum utile. |
Bien évidemment,
on peut donner une valeur de scrollTop négative, ce qui aura
pour effet de descendre encore le texte dans la fenêtre visible du sprite,
jusqu'à le faire disparaître par le bas.
De la même manière, si, lorsque la dernière ligne du texte
est visible, on continue à augmenter le scrollTop, on finira
par faire disparaître le texte mais cette fois-ci par le haut.
On voit donc se dessiner la structure de cette nouvelle version de l'animation :
- on a rajouté
une ligne dans le prepareMovie, de manière que le scrollTop
du texte soit nul (c'est à dire que la première ligne du texte
est visible). C'est une précaution un peu inutile mais elle permet de
s'assurer de tous les défauts possibles au démarrage, en forçant
cette propriété.
Notre prepareMovie
devient donc :
on
prepareMovie
t
= timeout("g").new(250, #moteur)
member("cherche").text
= ""
member("leTexte").scrolltop
= 0
end
Ensuite, voyons le script (de comportement) de nos flèches :
Tout d'abord, de
manière à pouvoir utiliser le même script pour les deux
flèches, nous allons devoir déclarer la propriété
spriteNum, comme nous l'avons fait dans les exercices précédents.
Pour l'initialisation du sprite, nous ne savons pas encore si nous aurons besoin
d'autres propriétés, mais pour la cohérence logique, nous
écrirons un on beginSprite me, qui pour l'instant restera vide.
Puis, pour des questions de lisibilité de l'interface, comme nous l'avons déjà rencontré dans des exercices précédents, il va nous falloir introduire un effet de rollOver de façon à indiquer à l'utilisateur, qu'à ce moment-là, il peut cliquer. Nous avons déjà traité ce problème : inutile donc de nous y étendre. Rappelons simplement que l'événement rollOver n'existe pas en Lingo (*), et qu'on le remplace donc par deux événements on mouseEnter et on mouseLeave, pour déclencher un changement d'acteur dans le sprite (ici, nous remplacerons flh par flhAct, et flb par flbAct, respectivement, et également inversement sur le on mouseLeave).
Ensuite de quoi, de manière à ce que nos flèches sachent faire défiler le texte à chaque fois qu'on clique dessus, nous allons les doter d'un gestionnaire on mouseUp qui décrira les actions à mener à chaque survenance de l'événement on mouseUp.
Comment pourrait-on décrire, en pseudo-code, ces actions à mener ?
Quand
la flèche reçoit un événement on mouseUp
Si
la flèche est la flèche haute alors
![]()
décaler
le texte de 3 lignes vers le bas (c'est à dire diminuer le scrollTop)
Sinon
si la flèche est la flèche basse alors
![]()
décaler
le texte de 3 lignes vers le haut (c'est à dire augmenter le scrollTop)
fin
si
fin
Ce petit script
appelle trois remarques :
- Nous avons posé comme condition, dans le script précédent,
le sens de la flèche, haute ou basse. Comment va-t-on savoir sur quelle
flèche on a appuyé ? Tout simplement en testant le nom de l'acteur
du sprite.
Mais attention, il faut se souvenir qu'au moment où on clique, l'acteur
a été modifié par le gestionnaire on mouseEnter.
Il faudra donc faire attention à tester les nom flhAct
et flbAct (et non flh ou flb tout
court), sans quoi notre ascenseur ne marchera pas. C'est un détail qui
peut paraître idiot et évident, mais c'est une faute d'inattention
que l'on fait souvent, même avec de l'habitude, et qui entraîne
de nombreuses heures perdues en déboguage).
- Nous avons dit que nous allions déplacer le texte de 3 lignes vers
le haut ou vers le bas. Nous aurions pu dire de la même manière
que nous le déplacerions de 1, 20, ou 30 ou 47 ou n'importe quel nombre
de pixels vers le haut ou vers le bas, puisque le scrollTop est une
valeur exprimée en pixels. Notre ascenseur aurait alors parfaitement
fonctionné aussi. Mais que se passerait-il ?
Le nombre de pixels dont nous choisirions de déplacer le texte à
chaque mouseUp n'a aucune raison de correspondre à la hauteur
d'un nombre entier de lignes de texte. Nous aurions alors toutes les chances
d'avoir des lignes coupées horizontalement, ne laissant voir qu'une fraction
inférieure ou supérieure des caractères.
Là encore ce n'est pas très grave, et la fonctionnalité
principale de l'ascenseur est respectée. Mais c'est totalement disgracieux,
et encore une fois peu professionnel !
Pour y remédier, Lingo fournit une autre propriété des
champs texte, qui va nous donner la hauteur des lignes en pixels en fonction
de la taille des caractères utilisés. Cette propriété
s'appelle lineHeight. Donc, si nous augmentons ou
diminuons le scrollTop de notre acteur champ d'un multiple entier de
la hauteur des lignes, alors nous serons sûrs que le texte sera horizontalement
coupé de manière correcte.
- Dans ce que nous avons écrit, si le texte est en position basse (c'est
à dire que la première ligne est visible), rien n'empêche
l'utilisateur de continuer à cliquer et donc à faire descendre
le texte. Ce n'est pas très grave mais ce n'est pas très beau
non plus.
De la même manière, si le texte est en position totalement haute,
c'est à dire que la dernière ligne est visible, rien n'empêche
l'utilisateur de continuer à cliquer et donc de continuer à faire
monter le texte. Même remarque que précédemment.
Il va donc falloir nous doter de limitations qui empêcheront tout déplacement
de texte quand celui-ci est à sa position maximum pour la flèche
considérée. Ceci sera réalisé par l'ajout de nouvelles
conditions.
Quelles sont maintenant les valeurs limites du scrollTop ?
Pour la position basse maximum (c'est à dire le scrollTop minimum),
c'est facile : c'est 0. En effet, la première ligne du texte est alors
visible, et il faut qu'on ne puisse plus appuyer sur la flèche haute
pour faire descendre plus le texte. Cette situation correspond à la figure
1 des schémas ci-dessus.
Pour la position
haute maximum (c'est à dire scrollTop maximum), on voit sur
la figure 3 que ce scrollTop maximum est égal à la hauteur
totale du texte (en pixels) moins la hauteur du sprite.
La hauteur du sprite nous est connue : elle est donnée par la
propriété height des sprites : sprite(n). height
(que nous avons déjà rencontrée dans les exercices précédents).
Pour les acteurs champ, les concepteurs du langage nous ont donné exactement
la même propriété, et nous allons pouvoir écrire
member("leTexte").height.
NB :La propriété
height des acteurs n'est du reste pas réservée aux acteurs champs
: tous les acteurs ont une propriété height, sauf les sons, évidement.
La valeur maximum du scrollTop nous sera donc donnée par la relation : member("leTexte").height - sprite(n).height (si le texte se trouve placé sur le sprite numéro n).
Je passe sur les rollOver qui vont donner ceci en Lingo :
on
mouseEnter me
if
sprite(spriteNum).member.name = "flh" then
![]()
sprite(spriteNum).member
= "flhAct"
else
if sprite(spriteNum).member.name = "flb" then
![]()
sprite(spriteNum).member
= "flbAct"
end
if
end
on
mouseLeave me
if
sprite(spriteNum).member.name = "flhAct" then
![]()
sprite(spriteNum).member
= "flh"
else
if sprite(spriteNum).member.name = "flbAct" then
![]()
sprite(spriteNum).member
= "flb"
end
if
end
Pour notre mouseUp, notre gestionnaire, toujours en pseudo-code, va donc devenir :
Quand la flèche reçoit un événement on mouseUp
Si
le nom de l'acteur du sprite vaut "flhAct" alors
![]()
si
le scrollTop du member "leTexte > 0 alors
![]()
![]()
le
scrollTop du member "leTexte" est diminué de trois fois la
hauteur de ligne du member "leTexte"
![]()
fin
si
Sinon
si le nom de l'acteur du sprite vaut "flbAct" alors
![]()
montéeMaxi
= la hauteur du member "leTexte" - la hauteur du sprite qui contient
le member "leTexte" (le 11 dans l'exercice)
![]()
Si
le scrollTop du memeber "leTexte" < montéeMaxi alors
![]()
![]()
le
scrollTop du member "leTexte" est augmenté de trois fois la
hauteur de ligne du member "leTexte"
![]()
fin
si
fin
si
fin
Et en code :
on mouseUp
me
if sprite(spriteNum).member.name
= "flhAct" then
![]()
if
member("leTexte").scrolltop > 0 then
![]()
![]()
member("leTexte").scrolltop
= member("leTexte").scrolltop - (3* member("leTexte").lineHeight)
![]()
end
if
else if sprite(spriteNum).member.name
= "flbAct" then
![]()
monteeMaxi
= member("leTexte").height - sprite(11).height
![]()
if
member("leTexte").scrolltop < monteeMaxi then
![]()
![]()
member("leTexte").scrolltop
= member("leTExte").scrolltop + (3*member("leTexte").lineHeight)
![]()
end
if
end if
end
A ce stade, nous
avons donc réalisé ce que nous nous proposions d'obtenir : deux
flèches qui signalent qu'on peut les cliquer quand on passe dessus, et
qui, quand on les clique effectivement, font se décaler le texte de trois
lignes vers le haut ou vers le bas.
Mais, si l'on veut se déplacer plus avant dans le texte, quel que soit
le sens, alors il faut cliquer le nombre de fois voulu pour atteindre l'endroit
désiré.
Dans l'étape suivante, nous allons voir comment réaliser un vrai ascenseur, lequel fonctionne en continu.
(*)Il existe une propriété rollOver des sprites, mais ce n'est pas un événement ; on ne peut donc pas s'en servir comme d'un déclencheur en dehors d'un autre événement répétitif qui surveillerait la valeur de cette propriété.
| Retour à première étape |