Подтвердить что ты не робот

Использование jquery для получения позиции элемента относительно области просмотра

Какой правильный способ получить позицию элемента на странице относительно окна просмотра (а не документа). jQuery.offset показалась многообещающей:

Получить текущие координаты первого элемента или установить координаты каждого элемента, в наборе согласованных элементов, относительных к документу.

Но это относительно документа. Есть ли эквивалентный метод, который возвращает смещения относительно окна просмотра?

4b9b3361

Ответ 1

Посмотрите плагин Dimensions, в частности scrollTop()/scrollLeft(). Информацию можно найти на http://api.jquery.com/scrollTop.

Ответ 2

Самый простой способ определить размер и положение элемента - вызвать его метод getBoundingClientRect(). Этот метод возвращает позиции элементов в координатах области просмотра. Он не ожидает аргументов и возвращает объект со свойствами left, right, top и bottom. Свойства left и top дают координаты X и Y верхнего левого угла элемента, а свойства right и bottom дают координаты нижнего правого угла.

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

Поддерживается везде.

Ответ 3

Вот две функции, чтобы получить высоту страницы и количество прокрутки (x, y) без использования плагинов (раздутых) размеров:

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

Ответ 4

jQuery.offset необходимо объединить с scrollTop и scrollLeft, как показано на этой диаграмме:

viewport scroll and element offset

Демо:

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>

Ответ 5

Вот функция, которая вычисляет текущую позицию элемента в окне просмотра:

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

Возвращаемые значения рассчитываются следующим образом:

Использование:

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

Демо:

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>

Ответ 6

Я обнаружил, что ответ cballou больше не работал в Firefox по состоянию на январь 2014 года. В частности, if (self.pageYOffset) не срабатывал, если клиент прокручивался вправо, но не вниз, потому что 0 - это число ложных, Это продолжалось некоторое время, потому что Firefox поддерживал document.body.scrollLeft/Top, но это больше не работает для меня (в Firefox 26.0).

Здесь мое модифицированное решение:

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. Почти наверняка работает над более старыми версиями всех из них.