Télécharger le .dir correspondant à cette étape
(bouton droit -> enregistrer la cible)


Deuxième étape :

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
Passer à la troisième étape