Использование jquery для получения позиции элемента относительно видового экрана
Как правильно получить положение элемента на странице относительно окна просмотра (а не документа). jQuery.offset
функция казалась многообещающей:
получить текущие координаты первого элемента, или установить координаты каждого элемента в наборе совпавших элементов, относительной к документу.
но это относительно документа. Существует ли эквивалентный метод, который возвращает смещения относительно видовое окно?
6 ответов:
посмотрите в размеры плагина, в частности
scrollTop()
/scrollLeft()
. Информацию можно найти по адресу http://api.jquery.com/scrollTop.
самый простой способ определить размер и положение элемента, чтобы вызвать его getBoundingClientRect() метод. Этот метод возвращает позиции элементов в координатах видового экрана. Он не ожидает никаких аргументов и возвращает объект с свойства слева, справа, сверху и дно. Левые и верхние свойства дают X и Y координаты верхнего левого угла элемента и свойства Right и bottom дайте координаты нижнего правого угол.
element.getBoundingClientRect(); // Get position in viewport coordinates
везде поддерживается.
вот две функции для получения высоты страницы и количества прокрутки (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 }
jQuery.offset
должен быть объединен сscrollTop
иscrollLeft
как показано на этой диаграмме:демо:
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>
вот функция, которая вычисляет текущее положение элемента в окне просмотра:
/** * 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>
я обнаружил, что ответ cballou больше не работает в Firefox по состоянию на январь. 2014. В частности,
if (self.pageYOffset)
не сработало, если клиент прокрутил вправо, но не вниз-потому что0
- номер falsey. Это прошло незамеченным на некоторое время, потому что 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. Почти наверняка работает на более старые версии всех из них.