Pour déplacer des éléments, nous devons être familiers avec les coordonnées.
La plupart des méthodes JavaScript traitent de lâun des deux systèmes de coordonnées :
- Par rapport à la fenêtre â similaire Ã
position:fixed, calculé à partir du bord supérieur/gauche de la fenêtre.- nous désignerons ces coordonnées comme
clientX/clientY, le raisonnement pour un tel nom deviendra clair plus tard, lorsque nous étudierons les propriétés de lâévénement.
- nous désignerons ces coordonnées comme
- Par rapport au document â similaire Ã
position:absolueà la racine du document, calculé à partir du bord supérieur/gauche du document.- nous les dénotons
pageX/pageY.
- nous les dénotons
Lorsque la page défile jusquâau tout début, de sorte que le coin supérieur/gauche de la fenêtre soit exactement le coin supérieur/gauche du document, ces coordonnées sont égales. Mais après le déplacement du document, les coordonnées relatives à la fenêtre des éléments changent, à mesure que les éléments se déplacent à travers la fenêtre, tandis que les coordonnées relatives au document restent les mêmes.
Sur cette image, nous prenons un point dans le document et démontrons ses coordonnées avant le défilement (à gauche) et après (à droite) :
Lorsque le document défile :
pageYâ La coordonnée relative au document est restée la même, elle est comptée à partir du haut du document (maintenant défilée).clientYâ la coordonnée relative à la fenêtre a changé (la flèche est devenue plus courte), car le même point sâest rapproché du haut de la fenêtre.
Coordonnées des éléments : getBoundingClientRect
La méthode elem.getBoundingClientRect() renvoie les coordonnées de la fenêtre pour un rectangle minimal qui entoure elem en tant quâobjet de la classe intégrée DOMRect.
Propriétés principales de DOMRect :
x/yâ Coordonnées X/Y de lâorigine du rectangle par rapport à la fenêtre,width/heightâ largeur/hauteur du rectangle (peut être négatif).
De plus, il existe des propriétés dérivées :
top/bottomâ Coordonnée Y pour le bord supérieur/inférieur du rectangle,left/rightâ Coordonnée X pour le bord du rectangle gauche/droit.
Par exemple, cliquez sur ce bouton pour voir les coordonnées de sa fenêtre :
Si vous faites défiler la page et répétez, vous remarquerez que lorsque la position du bouton relatif à la fenêtre change, ses coordonnées de fenêtre (y/top/bottom si vous faites défiler verticalement) changent également.
Voici lâimage de la sortie de elem.getBoundingClientRect() :
Comme vous pouvez le voir, x/y et width/height décrivent entièrement le rectangle. Les propriétés dérivées peuvent être facilement calculées à partir dâeux :
left = xtop = yright = x + widthbottom = y + height
Veuillez noter :
- Les coordonnées peuvent être des fractions décimales, telles que
10.5. Câest normal, le navigateur utilise en interne des fractions dans les calculs. Nous nâavons pas à les arrondir lors de la définition destyle.left/top. - Les coordonnées peuvent être négatives. Par exemple, si la page défile de sorte que
elemse trouve maintenant au-dessus de la fenêtre, alorselem.getBoundingClientRect().topest négatif.
top/left existent-ils sâil y a x/y ?Mathématiquement, un rectangle est défini de façon unique avec son point de départ (x,y) et le vecteur de direction (width,height). Les propriétés dérivées supplémentaires sont donc pour plus de commodité.
Techniquement, il est possible que width/height soit négatif, ce qui permet un rectangle âdirigéâ, par exemple pour représenter la sélection de la souris avec un début et une fin correctement marqués.
Les valeurs négatives de width/height signifient que le rectangle commence à son coin inférieur droit puis âgranditâ de gauche à droite.
Voici un rectangle avec une width et height (par exemple width=-200, height=-100) :
Comme vous pouvez le voir, left/top nâest pas égal à x/y dans ce cas.
En pratique cependant, elem.getBoundingClientRect() retourne toujours une largeur/hauteur positive, ici nous mentionnons une largeur/hauteur négative uniquement pour que vous compreniez pourquoi ces propriétés apparemment en double ne sont pas en fait des doublons.
x/yInternet Explorer ne prend pas en charge les propriétés x/y pour des raisons historiques.
Nous pouvons donc soit faire un polyfill (ajouter des getters dans DomRect.prototype), soit simplement utiliser top/left, car ils sont toujours les mêmes que x/y pour un
width/height positif, en particulier dans le résultat de elem.getBoundingClientRect().
Il existe des similitudes évidentes entre les coordonnées relatives à la fenêtre et CSS position:fixed.
Mais dans le positionnement CSS, la propriété right signifie la distance par rapport au bord droit, et la propriété bottom signifie la distance par rapport au bord inférieur.
Si nous regardons simplement lâimage ci-dessus, nous pouvons voir quâen JavaScript, ce nâest pas le cas. Toutes les coordonnées de la fenêtre sont comptées à partir du coin supérieur gauche, y compris celles-ci.
elementFromPoint(x, y)
Lâappel à document.elementFromPoint(x,y) renvoie lâélément le plus imbriqué aux coordonnées de la fenêtre (x,y).
La syntaxe est :
let elem = document.elementFromPoint(x, y);
Par exemple, le code ci-dessous met en évidence et génère la balise de lâélément qui se trouve maintenant au milieu de la fenêtre :
let centerX = document.documentElement.clientWidth / 2;
let centerY = document.documentElement.clientHeight / 2;
let elem = document.elementFromPoint(centerX, centerY);
elem.style.background = "red";
alert(elem.tagName);
Comme il utilise les coordonnées de la fenêtre, lâélément peut être différent selon la position de défilement actuelle.
elementFromPoint renvoie nullLa méthode document.elementFromPoint(x,y) ne fonctionne que si (x,y) se trouve à lâintérieur de la zone visible.
Si lâune des coordonnées est négative ou dépasse la largeur/hauteur de la fenêtre, elle renvoie alors null.
Voici une erreur typique qui peut se produire si nous ne la vérifions pas :
let elem = document.elementFromPoint(x, y);
// si les coordonnées se trouvent hors de la fenêtre, alors elem = null
elem.style.background = ''; // Error!
Utilisation pour un positionnement âfixeâ
La plupart du temps, nous avons besoin de coordonnées pour positionner quelque chose.
Pour afficher quelque chose près dâun élément, nous pouvons utiliser getBoundingClientRect pour obtenir ses coordonnées, puis position CSS avec left/top (ou right/bottom).
Par exemple, la fonction createMessageUnder(elem, html) ci-dessous affiche le message sous elem :
let elem = document.getElementById("coords-show-mark");
function createMessageUnder(elem, html) {
// créer un élément de message
let message = document.createElement('div');
// mieux utiliser une classe css pour le style ici
message.style.cssText = "position:fixed; color: red";
// attribuez des coordonnées, n'oubliez pas "px" !
let coords = elem.getBoundingClientRect();
message.style.left = coords.left + "px";
message.style.top = coords.bottom + "px";
message.innerHTML = html;
return message;
}
// Utilisation :
// l'ajouter pendant 5 secondes dans le document
let message = createMessageUnder(elem, 'Hello, world!');
document.body.append(message);
setTimeout(() => message.remove(), 5000);
Cliquez sur le bouton pour lâexécuter :
Le code peut être modifié pour afficher le message à gauche, à droite, en dessous, appliquer des animations CSS pour un âfonduâ et ainsi de suite. Câest facile, car nous avons toutes les coordonnées et tailles de lâélément.
Mais notez le détail important : lorsque la page défile, le message sâéloigne du bouton.
La raison en est évidente: lâélément de message repose sur position:fixed, il reste donc au même endroit de la fenêtre pendant que la page défile.
Pour changer cela, nous devons utiliser des coordonnées basées sur des documents et position:absolute.
Coordonnées du document
Les coordonnées relatives au document commencent dans le coin supérieur gauche du document, pas dans la fenêtre.
En CSS, les coordonnées de la fenêtre correspondent à position:fixed, tandis que les coordonnées du document sont similaires à position:absolue en haut.
Nous pouvons utiliser position:absolu et top/left pour placer quelque chose à un certain endroit du document, afin quâil y reste pendant un défilement de page. Mais nous avons dâabord besoin des bonnes coordonnées.
Il nây a pas de méthode standard pour obtenir les coordonnées du document dâun élément. Mais câest facile de lâécrire.
Les deux systèmes de coordonnées sont reliés par la formule :
pageY=clientY+ hauteur de la partie verticale déroulée du document.pageX=clientX+ largeur de la partie horizontale déroulée du document.
La fonction getCoords(elem) prendra les coordonnées de la fenêtre de elem.getBoundingClientRect() et leur ajouter le défilement actuel :
// obtenir les coordonnées du document de l'élément
function getCoords(elem) {
let box = elem.getBoundingClientRect();
return {
top: box.top + window.pageYOffset,
right: box.right + window.pageXOffset,
bottom: box.bottom + window.pageYOffset,
left: box.left + window.pageXOffset
};
}
Si dans lâexemple ci-dessus, nous lâavons utilisé avec position:absolue, le message resterait près de lâélément en défilement.
La fonction createMessageUnder modifiée :
function createMessageUnder(elem, html) {
let message = document.createElement('div');
message.style.cssText = "position:absolute; color: red";
let coords = getCoords(elem);
message.style.left = coords.left + "px";
message.style.top = coords.bottom + "px";
message.innerHTML = html;
return message;
}
Résumé
Nâimporte quel point de la page a des coordonnées :
- Par rapport à la fenêtre â
elem.getBoundingClientRect(). - Par rapport au document â
elem.getBoundingClientRect()plus le défilement de la page actuelle.
Les coordonnées de la fenêtre sont excellentes à utiliser avec position:fixed, et les coordonnées du document fonctionnent bien avec position:absolue.
Les deux systèmes de coordonnées ont leurs avantages et leurs inconvénients; il y a des moments où nous avons besoin de lâun ou de lâautre, tout comme position CSS absolute et fixed.
Commentaires
<code>, pour plusieurs lignes â enveloppez-les avec la balise<pre>, pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepenâ¦)