web-dev-qa-db-fra.com

Utiliser jquery pour obtenir la position de l'élément par rapport à la fenêtre d'affichage

Quelle est la bonne façon d'obtenir la position d'un élément sur la page par rapport à la fenêtre d'affichage (plutôt qu'au document). jQuery.offset la fonction semblait prometteuse:

Obtenez les coordonnées actuelles du premier élément ou définissez les coordonnées de chaque élément dans l'ensemble d'éléments correspondants, par rapport au document.

Mais c'est relatif au document. Existe-t-il une méthode équivalente qui renvoie des décalages par rapport à la fenêtre?

112
DA.

Regardez dans le plugin Dimensions, en particulier scrollTop()/scrollLeft(). Les informations peuvent être trouvées à http://api.jquery.com/scrollTop .

25
Agent_9191

Le moyen le plus simple de déterminer la taille et la position d’un élément est d’appeler sa méthode getBoundingClientRect () . Cette méthode retourne les positions des éléments dans les coordonnées de la fenêtre. Il n'attend aucun argument et retourne un objet avec les propriétés left, right, top et bottom . Les propriétés left et top donnent les coordonnées X et Y du coin supérieur gauche de l'élément, tandis que les propriétés right et bottom indiquent les coordonnées du coin inférieur droit.

element.getBoundingClientRect(); // Get position in viewport coordinates

Pris en charge partout.

278
Igor G.

Voici deux fonctions pour obtenir la hauteur de la page et les montants de défilement (x, y) sans utiliser le plugin Dimensions (gonflé):

// getPageScroll() by quirksmode.com
function getPageScroll() {
    var xScroll, yScroll;
    if (self.pageYOffset) {
      yScroll = self.pageYOffset;
      xScroll = self.pageXOffset;
    } else if (document.documentElement && document.documentElement.scrollTop) {
      yScroll = document.documentElement.scrollTop;
      xScroll = document.documentElement.scrollLeft;
    } else if (document.body) {// all other Explorers
      yScroll = document.body.scrollTop;
      xScroll = document.body.scrollLeft;
    }
    return new Array(xScroll,yScroll)
}

// Adapted from getPageSize() by quirksmode.com
function getPageHeight() {
    var windowHeight
    if (self.innerHeight) { // all except Explorer
      windowHeight = self.innerHeight;
    } else if (document.documentElement && document.documentElement.clientHeight) {
      windowHeight = document.documentElement.clientHeight;
    } else if (document.body) { // other Explorers
      windowHeight = document.body.clientHeight;
    }
    return windowHeight
}
40
Corey Ballou

jQuery.offset doit être combiné avec scrollTop et scrollLeft comme indiqué dans ce diagramme:

viewport scroll and element offset

Démo:

function getViewportOffset($e) {
  var $window = $(window),
    scrollLeft = $window.scrollLeft(),
    scrollTop = $window.scrollTop(),
    offset = $e.offset(),
    rect1 = { x1: scrollLeft, y1: scrollTop, x2: scrollLeft + $window.width(), y2: scrollTop + $window.height() },
    rect2 = { x1: offset.left, y1: offset.top, x2: offset.left + $e.width(), y2: offset.top + $e.height() };
  return {
    left: offset.left - scrollLeft,
    top: offset.top - scrollTop,
    insideViewport: rect1.x1 < rect2.x2 && rect1.x2 > rect2.x1 && rect1.y1 < rect2.y2 && rect1.y2 > rect2.y1
  };
}
$(window).on("load scroll resize", function() {
  var viewportOffset = getViewportOffset($("#element"));
  $("#log").text("left: " + viewportOffset.left + ", top: " + viewportOffset.top + ", insideViewport: " + viewportOffset.insideViewport);
});
body { margin: 0; padding: 0; width: 1600px; height: 2048px; background-color: #CCCCCC; }
#element { width: 384px; height: 384px; margin-top: 1088px; margin-left: 768px; background-color: #99CCFF; }
#log { position: fixed; left: 0; top: 0; font: medium monospace; background-color: #EEE8AA; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<!-- scroll right and bottom to locate the blue square -->
<div id="element"></div>
<div id="log"></div>
18
Salman A

Voici une fonction qui calcule la position actuelle d'un élément dans la fenêtre:

/**
 * Calculates the position of a given element within the viewport
 *
 * @param {string} obj jQuery object of the dom element to be monitored
 * @return {array} An array containing both X and Y positions as a number
 * ranging from 0 (under/right of viewport) to 1 (above/left of viewport)
 */
function visibility(obj) {
    var winw = jQuery(window).width(), winh = jQuery(window).height(),
        elw = obj.width(), elh = obj.height(),
        o = obj[0].getBoundingClientRect(),
        x1 = o.left - winw, x2 = o.left + elw,
        y1 = o.top - winh, y2 = o.top + elh;

    return [
        Math.max(0, Math.min((0 - x1) / (x2 - x1), 1)),
        Math.max(0, Math.min((0 - y1) / (y2 - y1), 1))
    ];
}

Les valeurs de retour sont calculées comme ceci:

Usage:

visibility($('#example'));  // returns [0.3742887830933581, 0.6103752759381899]

Démo:

function visibility(obj) {var winw = jQuery(window).width(),winh = jQuery(window).height(),elw = obj.width(),
    elh = obj.height(), o = obj[0].getBoundingClientRect(),x1 = o.left - winw, x2 = o.left + elw, y1 = o.top - winh, y2 = o.top + elh; return [Math.max(0, Math.min((0 - x1) / (x2 - x1), 1)),Math.max(0, Math.min((0 - y1) / (y2 - y1), 1))];
}
setInterval(function() {
  res = visibility($('#block'));
  $('#x').text(Math.round(res[0] * 100) + '%');
  $('#y').text(Math.round(res[1] * 100) + '%');
}, 100);
#block { width: 100px; height: 100px; border: 1px solid red; background: yellow; top: 50%; left: 50%; position: relative;
} #container { background: #EFF0F1; height: 950px; width: 1800px; margin-top: -40%; margin-left: -40%; overflow: scroll; position: relative;
} #res { position: fixed; top: 0; z-index: 2; font-family: Verdana; background: #c0c0c0; line-height: .1em; padding: 0 .5em; font-size: 12px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="res">
  <p>X: <span id="x"></span></p>
  <p>Y: <span id="y"></span></p>
</div>
<div id="container"><div id="block"></div></div>
2
Arne

J'ai découvert que la réponse de cballou ne fonctionnait plus dans Firefox depuis janvier 2014. Plus précisément, if (self.pageYOffset) ne se déclenche pas si le client a fait défiler l'écran à droite, mais pas vers le bas, car 0 est un numéro de falsey. Cela n'a pas été détecté pendant un moment parce que Firefox supportait document.body.scrollLeft/Top, mais cela ne fonctionne plus pour moi (sur Firefox 26.0).

Voici ma solution modifiée:

var getPageScroll = function(document_el, window_el) {
  var xScroll = 0, yScroll = 0;
  if (window_el.pageYOffset !== undefined) {
    yScroll = window_el.pageYOffset;
    xScroll = window_el.pageXOffset;
  } else if (document_el.documentElement !== undefined && document_el.documentElement.scrollTop) {
    yScroll = document_el.documentElement.scrollTop;
    xScroll = document_el.documentElement.scrollLeft;
  } else if (document_el.body !== undefined) {// all other Explorers
    yScroll = document_el.body.scrollTop;
    xScroll = document_el.body.scrollLeft;
  }
  return [xScroll,yScroll];
};

Testé et fonctionnant dans FF26, Chrome 31, IE11. Fonctionne presque certainement sur les anciennes versions de toutes.

0
p.g.l.hall