Déplacement et défilement dans une page en javascript
Déplacement lent et continu
- Paragraphe 1: un texte inutile, qui prend de la place, généré par une ligne de php
- Déplacement doux et continu: Fonction javascript dans un lien
- Fonction javascript appliquée à tous les liens internes d'une page
- Une autre section inutile, qui prend de la place dans la page générée aussi par une ligne de php
- Bas de la page
Paragraphe 1: un texte inutile, qui prend de la place
Du texte qui prend de la placeEncore…et encore …
et Re …Du texte qui prend de la place
Encore…et encore …
et Re …Du texte qui prend de la place
Encore…et encore …
et Re …Du texte qui prend de la place
Encore…et encore …
et Re …Du texte qui prend de la place
Encore…et encore …
et Re …Du texte qui prend de la place
Encore…et encore …
et Re …Du texte qui prend de la place
Encore…et encore …
et Re …Du texte qui prend de la place
Encore…et encore …
et Re …Du texte qui prend de la place
Encore…et encore …
et Re …Du texte qui prend de la place
Encore…et encore …
et Re …
Code php qui génère ce texte inutile
- Code:Select all
<?php for ($i=0;$i<20;$i++) {echo "Du texte qui prend de la place<br>Encore…et encore …<br>et Re …";}?>
Du texte qui prend de la place
Encore…et encore …
et Re …Du texte qui prend de la place
Encore…et encore …
et Re …Du texte qui prend de la place
Encore…et encore …
et Re …Du texte qui prend de la place
Encore…et encore …
et Re …Du texte qui prend de la place
Encore…et encore …
et Re …Du texte qui prend de la place
Encore…et encore …
et Re …Du texte qui prend de la place
Encore…et encore …
et Re …Du texte qui prend de la place
Encore…et encore …
et Re …Du texte qui prend de la place
Encore…et encore …
et Re …Du texte qui prend de la place
Encore…et encore …
et Re …
Fonction javascript dans un lien
- Code:Select all
<!-- Lien html-->
<a href="javascript:ScrollSmoothlyToId('Bottom')">Go smoothly to bottom</a>
<script>// fonction javascript
function ScrollSmoothlyToId(id) {
d=document.getElementById(id).offsetTop-window.pageYOffset;
move=60;// Nombre total de déplacements
for (i=1;i<move;i++) {setTimeout(function () {window.scrollBy(0,d/move);},i*i);}
// Après tous les déplacements:
setTimeout(function() {
// On ajuste la position
d=document.getElementById(id).offsetTop-window.pageYOffset;window.scrollBy(0,d);
// On ajoute le lien dans la barre d'adresse
location.href="#"+id;
},
move*move);
}
</script>
- Affichage:
-
Go smoothly to bottom
Description/explication
- On appelle
une fonction javascript directement dans le lien
href
de la balise <a>
(même si, comme nous allons le voir dans l'alternative ci-dessous, ce n'est pas forcément la meilleure méthode).
- Ensuite, la
variable
d
contient l'écart entre les distances au
haut da lap ge de la balise cible et de la distance actuelle au
haut de la page.
(voir par exemple cette page pour plus de détail sur la gestion des coordonnées en javascript dans une page)
d
est la distance dont il va falloir se déplacer en tout dans la page.
On effectuera ce déplacement global en move
déplacements:
- l'animation se gère en gérant le temps d'exécution,
via
setTimeout
(voir Gestion du temps et animation en javascript),
de chaque déplacement successif de d/move
- l'effet d'animation "adaptatif", ou doux,
c'est-à-dire ici qui ralentit le déplacement lorsqu'il se rapproche
de l'id cible se fait en jouant sur les délais
d'exécution:
i*i
.
Au tout début, i vaut 1, donc le premier déplacement se fait très rapidement (le délai de setTimeout
est en millisecondes), puis i=2, donc i*i=4 et l'exécution est un peu plus
retardée, etc …
Bien sûr le code peut être adaptée en changeant soit le nombre
de dépalcements (variable move
), soit le délai entre
exécutions (i*i
, ou un cube i*i*i
, ou
d'autres fonctions plus ou moins évoluées).
Par exemple, pour avoir seulement un effet continu, il suffit de
remplacer les délais i*i
par des délais
linéaires i
, ou 10*i
, …
- Enfin, on ajuste (éventuellement) le dernier déplacement pour
tomber juste sur l'id ciblé,
et on ajoute l'ancre lié en lien dans l'adresse de la page.
Fonction appliquée à tous les liens internes d'une page
On peut aussi rédiger ses pages en html sans tenir à ce moment compte du
comportement lors de clicks sur des liens internes,
comportement qui sera alors imposé par une couche javascript finale et indépendante.
Cette solution est même préférable car:
- elle permet de séparer le fond (le texte brut), la forme (la mise
en page html+css, avec la balise <a href="…"… ) et
le comportement lors d'interaction avec l'utilisateur.
- si javascript est désactivé chez le lecteur et utilisateur (côté
client donc), les liens internes fonctionneront quand même
correctement, mais simplement avec le comportement par défaut du
navigateur client
- la structure sémantique du document est conservée, surtout n'est
pas camouflée dans un certain code (qui plus est interprété correctement
par le navigateur on espère), ce qui peut être d'une grande
importance, pour les moteurs de recherche par exemple.
- elle est plus générale que l'utilisation de
onclick
via <a href="#" onclick="…">
,
qui indique que le comportement affecté doit être lancé avec un
click de souris. Ici, c'est le comportement du lien qui est
contrôlé, qu'il soit lancé effectivement avec un click de souris, ou
autrement (clavier, tactile, …)
Code
- Code:Select all
<!-- Exemples de Liens html-->
<a href="#Bottom">Go smoothly to bottom</a><br>
<a href="#Top">Go smoothly to top</a>;<br>
<a href="#Code">Go smoothly to previuos javascript code</a>
<script>// javascript global
links=document.getElementsByTagName("a");
for (i=0;i<links.length;i++) {
if ((links[i].href).match(/#/)) {
links[i].addEventListener('click', function(e) {
e.preventDefault();
innerlink=""+(((e.currentTarget).href).match(/#.*/));
ScrollSmoothlyToId(innerlink.substring(1,innerlink.length));
}
)
}
}
</script>
Description/explication de la fonction globale
- Dans un premier temps, on utilise la méthode
getElementsByTagName
qui, appliquée
au document entier, retourne dans la variable links
la
liste des noeuds du document contenant des liens (tag, ou balise, "a").
On peut alors balayer tous les liens de la page l'un après l'autre
- Il s'agit ensuite de tester s'il s'agit d'un lien interne ou non;
on teste pour cela la présence du caractère "#"
à la ligne suivante
- S'il s'agit bien d'un lien interne, on écoute les événement liés à
celui-ci, et on associe une fonction à l'événement
'click'
- On prévient tout d'abord le comportement par défaut du lien, qui aurait pour conséquence de sauter directement à l'ancre indiquée,
- on récupère le lien (élément
href
) de l'élément
sur lequel a été lancé l'événement click (ici donc le lien interne qui
nous intéresse), en ne sélectionnant que la sous chaîne de
caractère après le symbole "#".
Voir à ce sujet, des détails sur les expressions rationnelles.
- Enfin, on applique à ce lien interne, considéré comme l'id
d'un élément sur la page (sans le "#" qui est alors le premier
caractère de la chaîne
innerlink
qu'on lui soustrait), notre fonction précédente ScrollSmoothlyToId
.
Paragraphe suivant: encore de la place utilisée inutilement
Ligne inutile numéro: 1
Ligne inutile numéro: 2
Ligne inutile numéro: 3
Ligne inutile numéro: 4
Ligne inutile numéro: 5
Ligne inutile numéro: 6
Ligne inutile numéro: 7
Ligne inutile numéro: 8
Ligne inutile numéro: 9
Ligne inutile numéro: 10
Code php qui génère ce texte inutile
- Code:Select all
<?php for ($i=0;$i<=20;$i++) {echo "Ligne inutile numéro: ".$i."<br>";}?>
Ligne inutile numéro: 11
Ligne inutile numéro: 12
Ligne inutile numéro: 13
Ligne inutile numéro: 14
Ligne inutile numéro: 15
Ligne inutile numéro: 16
Ligne inutile numéro: 17
Ligne inutile numéro: 18
Ligne inutile numéro: 19
Ligne inutile numéro: 20
- Code:Select all
<?php for ($i=0;$i<20;$i++) {echo "Du texte qui prend de la place<br>Encore…et encore …<br>et Re …";}?>
- Code:Select all
<!-- Lien html-->
<a href="javascript:ScrollSmoothlyToId('Bottom')">Go smoothly to bottom</a>
<script>// fonction javascript
function ScrollSmoothlyToId(id) {
d=document.getElementById(id).offsetTop-window.pageYOffset;
move=60;// Nombre total de déplacements
for (i=1;i<move;i++) {setTimeout(function () {window.scrollBy(0,d/move);},i*i);}
// Après tous les déplacements:
setTimeout(function() {
// On ajuste la position
d=document.getElementById(id).offsetTop-window.pageYOffset;window.scrollBy(0,d);
// On ajoute le lien dans la barre d'adresse
location.href="#"+id;
},
move*move);
}
</script>
- Affichage:
-
Go smoothly to bottom
href
de la balise <a>
(même si, comme nous allons le voir dans l'alternative ci-dessous, ce n'est pas forcément la meilleure méthode).
d
contient l'écart entre les distances au
haut da lap ge de la balise cible et de la distance actuelle au
haut de la page.
(voir par exemple cette page pour plus de détail sur la gestion des coordonnées en javascript dans une page)
d
est la distance dont il va falloir se déplacer en tout dans la page.
On effectuera ce déplacement global en
move
déplacements:
- l'animation se gère en gérant le temps d'exécution,
via
setTimeout
(voir Gestion du temps et animation en javascript), de chaque déplacement successif ded/move
- l'effet d'animation "adaptatif", ou doux,
c'est-à-dire ici qui ralentit le déplacement lorsqu'il se rapproche
de l'id cible se fait en jouant sur les délais
d'exécution:
i*i
.
Au tout début, i vaut 1, donc le premier déplacement se fait très rapidement (le délai desetTimeout
est en millisecondes), puis i=2, donc i*i=4 et l'exécution est un peu plus retardée, etc …
Bien sûr le code peut être adaptée en changeant soit le nombre de dépalcements (variablemove
), soit le délai entre exécutions (i*i
, ou un cubei*i*i
, ou d'autres fonctions plus ou moins évoluées).
Par exemple, pour avoir seulement un effet continu, il suffit de remplacer les délaisi*i
par des délais linéairesi
, ou10*i
, …
onclick
via <a href="#" onclick="…">
,
qui indique que le comportement affecté doit être lancé avec un
click de souris. Ici, c'est le comportement du lien qui est
contrôlé, qu'il soit lancé effectivement avec un click de souris, ou
autrement (clavier, tactile, …)- Code:Select all
<!-- Exemples de Liens html-->
<a href="#Bottom">Go smoothly to bottom</a><br>
<a href="#Top">Go smoothly to top</a>;<br>
<a href="#Code">Go smoothly to previuos javascript code</a>
<script>// javascript global
links=document.getElementsByTagName("a");
for (i=0;i<links.length;i++) {
if ((links[i].href).match(/#/)) {
links[i].addEventListener('click', function(e) {
e.preventDefault();
innerlink=""+(((e.currentTarget).href).match(/#.*/));
ScrollSmoothlyToId(innerlink.substring(1,innerlink.length));
}
)
}
}
</script>
getElementsByTagName
qui, appliquée
au document entier, retourne dans la variable links
la
liste des noeuds du document contenant des liens (tag, ou balise, "a").
On peut alors balayer tous les liens de la page l'un après l'autre
'click'
- On prévient tout d'abord le comportement par défaut du lien, qui aurait pour conséquence de sauter directement à l'ancre indiquée,
- on récupère le lien (élément
href
) de l'élément sur lequel a été lancé l'événement click (ici donc le lien interne qui nous intéresse), en ne sélectionnant que la sous chaîne de caractère après le symbole "#". Voir à ce sujet, des détails sur les expressions rationnelles. - Enfin, on applique à ce lien interne, considéré comme l'id
d'un élément sur la page (sans le "#" qui est alors le premier
caractère de la chaîne
innerlink
qu'on lui soustrait), notre fonction précédenteScrollSmoothlyToId
.
- Code:Select all
<?php for ($i=0;$i<=20;$i++) {echo "Ligne inutile numéro: ".$i."<br>";}?>
Ligne inutile numéro: 12
Ligne inutile numéro: 13
Ligne inutile numéro: 14
Ligne inutile numéro: 15
Ligne inutile numéro: 16
Ligne inutile numéro: 17
Ligne inutile numéro: 18
Ligne inutile numéro: 19
Ligne inutile numéro: 20