Görüntü alanına göre öğenin konumunu almak için jquery kullanma


117

Sayfadaki bir öğenin konumunu görünüm alanına göre (belgeden ziyade) almanın doğru yolu nedir? jQuery.offsetişlev umut verici görünüyordu:

Belgeye göre eşleşen öğeler kümesindeki ilk öğenin geçerli koordinatlarını alın veya her öğenin koordinatlarını ayarlayın.

Ama bu belgeye göre. Görüntü alanına göre ofsetleri döndüren eşdeğer bir yöntem var mı?


5
NOT: @ Igor G'nin cevabına bakın ...
Carl Smith

3
DA'ya göre, Igor G'nin cevabını gerçekten kabul etmelisiniz, bu bir hayat kurtarıcı!
Vincent Duprez

Yanıtlar:



288

Bir öğenin boyutunu ve konumunu belirlemenin en kolay yolu, getBoundingClientRect () yöntemini çağırmaktır . Bu yöntem, görüntü alanı koordinatlarında öğe konumlarını döndürür. Hiçbir argüman beklemez ve sol, sağ, üst ve alt özelliklere sahip bir nesne döndürür . Sol ve üst özellikler, öğenin sol üst köşesinin X ve Y koordinatlarını verir ve sağ ve alt özellikler, sağ alt köşenin koordinatlarını verir.

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

Her yerde desteklenir.


15
Bu yöntemin IE5 tarafından eklenmesi inanılmaz ... bir şey iyi olduğunda, iyidir!
roy riojas

Bu ilk başta harika görünüyordu, ancak bir kullanıcının Mobile Safari 7'yi yakınlaştırmasını hesaba
katmıyor

2
En son firefox tarafından desteklenmiyorgetBoundingClientRect is not a function
user007

2
@ user007 En son firefox tarafından desteklendiğini onaylıyorum.
adriendenat

27
Harika cevap ve jquery yapmak için bunu basitçe şu şekilde yapın: $('#myElement')[0].getBoundingClientRect().top(veya başka bir pozisyonda)
Guillaume Arluison

40

Burada (şişirilmiş) boyutlar eklentisini kullanmadan sayfa yüksekliğini ve kaydırma miktarlarını (x, y) elde etmek için iki işlev vardır:

// 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
}

Bu harika. Çok kullanışlı.
Jimmy

Merak ettiğim için, bu durumda neden pencere yerine "self" özelliğini kullandınız?
dkugappi


23

jQuery.offsetile birleştirilmesi gerekir scrollTopve scrollLeftbu şemada gösterildiği gibi:

görüntü alanı kaydırma ve öğe uzaklığı

Demo:

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>


2
bu benim için harika çalıştı, ancak bunu bir araç ipucunun
Jordan

Bu kesinlikle, her durumda, doğru cevaptır. Diğerlerinin fare / kaydırma delta yapılandırmasına, tarayıcılara, obj konumuna vb. Bağlı sorunları var.
Pedro Ferreira

2

İşte bir elemanın görüntü alanı içindeki mevcut konumunu hesaplayan bir fonksiyon:

/**
 * 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))
    ];
}

Dönüş değerleri şu şekilde hesaplanır:

Kullanımı:

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

Demo:

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>


0

Cballou'nun cevabının Ocak 2014 itibariyle Firefox'ta artık çalışmadığını öğrendim. Özellikle, if (self.pageYOffset)müşteri sağa kaydırdığında tetiklenmedi, ancak aşağı kaydırmadı - çünkü yanlış 0bir sayı. Firefox document.body.scrollLeft/ desteklediği için bu bir süre tespit edilemedi Top, ancak bu artık benim için çalışmıyor (Firefox 26.0'da).

İşte benim değiştirilmiş çözümüm:

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];
};

FF26, Chrome 31, IE11'de test edildi ve çalışıyor. Neredeyse kesinlikle hepsinin eski sürümlerinde çalışıyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.