Получить позицию (X, Y) HTML-элемента - PullRequest
1293 голосов
/ 14 января 2009

Я хочу знать, как получить положение X и Y таких элементов HTML, как img и div в JavaScript.

Ответы [ 25 ]

14 голосов
/ 18 августа 2010

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

10 голосов
/ 01 декабря 2015

Я взял ответ @ meouw, добавил в clientLeft, который учитывает границы, а затем создал три версии:

getAbsoluteOffsetFromBody - аналогично @ meouw, получает абсолютную позицию относительно тела или html-элемента документа (в зависимости от режима причуд)

getAbsoluteOffsetFromGivenElement - возвращает абсолютную позицию относительно данного элемента (lativeEl). Обратите внимание, что данный элемент должен содержать элемент el, иначе он будет вести себя так же, как getAbsoluteOffsetFromBody. Это полезно, если у вас есть два элемента, содержащихся в другом (известном) элементе (необязательно, несколько узлов вверх по дереву узлов) и вы хотите сделать их одинаковыми.

getAbsoluteOffsetFromRelative - возвращает абсолютную позицию относительно первого родительского элемента с позицией: относительный. Это похоже на getAbsoluteOffsetFromGivenElement, по той же причине, но будет идти только до первого соответствующего элемента.

getAbsoluteOffsetFromBody = function( el )
{   // finds the offset of el from the body or html element
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
    {
        _x += el.offsetLeft - el.scrollLeft + el.clientLeft;
        _y += el.offsetTop - el.scrollTop + el.clientTop;
        el = el.offsetParent;
    }
    return { top: _y, left: _x };
}

getAbsoluteOffsetFromGivenElement = function( el, relativeEl )
{   // finds the offset of el from relativeEl
    var _x = 0;
    var _y = 0;
    while( el && el != relativeEl && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
    {
        _x += el.offsetLeft - el.scrollLeft + el.clientLeft;
        _y += el.offsetTop - el.scrollTop + el.clientTop;
        el = el.offsetParent;
    }
    return { top: _y, left: _x };
}

getAbsoluteOffsetFromRelative = function( el )
{   // finds the offset of el from the first parent with position: relative
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
    {
        _x += el.offsetLeft - el.scrollLeft + el.clientLeft;
        _y += el.offsetTop - el.scrollTop + el.clientTop;
        el = el.offsetParent;
        if (el != null)
        {
            if (getComputedStyle !== 'undefined')
                valString = getComputedStyle(el, null).getPropertyValue('position');
            else
                valString = el.currentStyle['position'];
            if (valString === "relative")
                el = null;
        }
    }
    return { top: _y, left: _x };
}

Если у вас все еще есть проблемы, особенно связанные с прокруткой, вы можете попробовать взглянуть на http://www.greywyvern.com/?post=331 - я заметил, по крайней мере, один фрагмент сомнительного кода в getStyle, который должен нормально работать, если браузеры ведут себя, но Остальное вообще проверял.

8 голосов
/ 14 января 2009

при использовании jQuery плагин размеры превосходен и позволяет вам точно указать, что вы хотите.

, например

Относительная позиция, абсолютная позиция, абсолютная позиция без заполнения, с дополнением ...

Это продолжается, давайте просто скажем, что с этим можно многое сделать.

Плюс бонусом использования jQuery является его легкий размер файла и простота использования, после чего вы не вернетесь к JavaScript.

7 голосов
/ 16 апреля 2013

Если вы используете jQuery, это может быть простое решение:

<script>
  var el = $("#element");
  var position = el.position();
  console.log( "left: " + position.left + ", top: " + position.top );
</script>
7 голосов
/ 10 сентября 2011

Это лучший код, который мне удалось создать (работает также в iframes, в отличие от смещения jQuery ()) Кажется, у webkit немного другое поведение.

На основании комментария Мёу:

function getOffset( el ) {
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
        _x += el.offsetLeft - el.scrollLeft;
        _y += el.offsetTop - el.scrollTop;
        // chrome/safari
        if ($.browser.webkit) {
            el = el.parentNode;
        } else {
            // firefox/IE
            el = el.offsetParent;
        }
    }
    return { top: _y, left: _x };
}
7 голосов
/ 25 августа 2016

Разница между маленьким и маленьким

function getPosition( el ) {
    var x = 0;
    var y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
    x += el.offsetLeft - el.scrollLeft;
    y += el.offsetTop - el.scrollTop;
    el = el.offsetParent;
    }
    return { top: y, left: x };
}

Посмотрите пример координат: http://javascript.info/tutorial/coordinates

6 голосов
/ 04 ноября 2014

Самый чистый подход, который я нашел, - это упрощенная версия метода, используемого jQuery's offset. Как и в некоторых других ответах, он начинается с getBoundingClientRect; Затем он использует window и documentElement для настройки положения прокрутки, а также такие вещи, как поле на body (часто по умолчанию).

var rect = el.getBoundingClientRect();
var docEl = document.documentElement;

var rectTop = rect.top + window.pageYOffset - docEl.clientTop;
var rectLeft = rect.left + window.pageXOffset - docEl.clientLeft;

var els = document.getElementsByTagName("div");
var docEl = document.documentElement;

for (var i = 0; i < els.length; i++) {

  var rect = els[i].getBoundingClientRect();

  var rectTop = rect.top + window.pageYOffset - docEl.clientTop;
  var rectLeft = rect.left + window.pageXOffset - docEl.clientLeft;

  els[i].innerHTML = "<b>" + rectLeft + ", " + rectTop + "</b>";
}
div {
  width: 100px;
  height: 100px;
  background-color: red;
  border: 1px solid black;
}
#rel {
  position: relative;
  left: 10px;
  top: 10px;
}
#abs {
  position: absolute;
  top: 250px;
  left: 250px;
}
<div id="rel"></div>
<div id="abs"></div>
<div></div>
5 голосов
/ 15 марта 2015

Я сделал это так, чтобы он был совместим со старыми браузерами.

// For really old browser's or incompatible ones
    function getOffsetSum(elem) {
        var top = 0,
            left = 0,
            bottom = 0,
            right = 0

         var width = elem.offsetWidth;
         var height = elem.offsetHeight;

        while (elem) {
            top += elem.offsetTop;
            left += elem.offsetLeft;
            elem = elem.offsetParent;
        }

         right = left + width;
         bottom = top + height;

        return {
            top: top,
            left: left,
            bottom: bottom,
            right: right,
        }
    }

    function getOffsetRect(elem) {
        var box = elem.getBoundingClientRect();

        var body = document.body;
        var docElem = document.documentElement;

        var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop;
        var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;

        var clientTop = docElem.clientTop;
        var clientLeft = docElem.clientLeft;


        var top = box.top + scrollTop - clientTop;
        var left = box.left + scrollLeft - clientLeft;
        var bottom = top + (box.bottom - box.top);
        var right = left + (box.right - box.left);

        return {
            top: Math.round(top),
            left: Math.round(left),
            bottom: Math.round(bottom),
            right: Math.round(right),
        }
    }

    function getOffset(elem) {
        if (elem) {
            if (elem.getBoundingClientRect) {
                return getOffsetRect(elem);
            } else { // old browser
                return getOffsetSum(elem);
            }
        } else
            return null;
    }

Подробнее о координатах в JavaScript здесь: http://javascript.info/tutorial/coordinates

3 голосов
/ 24 октября 2017

Хотя это, скорее всего, будет потеряно из-за большого количества ответов, лучшие решения здесь не работают для меня.
Насколько я мог сказать, ни один из других ответов не помог бы.

Положение
На странице HTML5 у меня было меню, которое было элементом nav внутри заголовка (не заголовок THE, а заголовок другого элемента).
Я хотел, чтобы навигация прилипала к вершине, как только пользователь прокручивал ее, но до этого заголовок располагался в абсолютном положении (поэтому я мог немного наложить его на что-то другое).
Приведенные выше решения никогда не вызывали изменений, потому что .offsetTop не собирался меняться, поскольку это был элемент с абсолютным позиционированием. Кроме того, свойство .scrollTop было просто вершиной самого верхнего элемента ... то есть 0 и всегда было бы 0.
Любые тесты, которые я выполнял, используя эти два (и то же самое с результатами getBoundingClientRect), не сообщали бы мне, прокручивалась ли верхняя часть навигационной панели до верхней части просматриваемой страницы (опять же, как сообщалось в консоли, они просто оставались теми же числами при прокрутке). произошло).

Решение
Решением для меня было использование

window.visualViewport.pageTop

Значение свойства pageTop отражает видимую часть экрана, поэтому я могу отслеживать, где находится элемент относительно границ видимой области.

Вероятно, нет необходимости говорить, что всякий раз, когда я имею дело с прокруткой, я ожидаю использовать это решение для программной реакции на движение прокручиваемых элементов.
Надеюсь, это поможет кому-то еще.
ВАЖНОЕ ПРИМЕЧАНИЕ: В настоящее время это работает в Chrome и Opera и определенно не работает в Firefox (6-2018) ... до тех пор, пока Firefox не поддерживает visualViewport. Я НЕ рекомендую использовать этот метод (и Я надеюсь, что они скоро сделают ... это имеет гораздо больше смысла, чем остальные).


UPDATE:
Просто примечание относительно этого решения.
Хотя я все еще нахожу, что обнаружил, что это очень ценно для ситуаций, в которых «... программно реагирует на движение прокручиваемых элементов». применимо. Лучшим решением проблемы, с которой я столкнулся, было использование CSS для установки position: sticky на элементе. Используя sticky, вы можете сделать так, чтобы элемент оставался наверху без использования javascript (ПРИМЕЧАНИЕ: бывают случаи, когда это не будет работать так же эффективно, как изменение элемента на fixed, но для большинства применений липкий подход, вероятно, будет лучше)

UPDATE01:
Таким образом, я понял, что для другой страницы у меня было требование, в котором мне нужно было определить положение элемента в слегка сложной настройке прокрутки (параллакс плюс элементы, которые прокручиваются мимо как часть сообщения). В этом сценарии я понял, что следующие данные предоставляют значение, которое я использовал, чтобы определить, когда что-то делать:

  let bodyElement = document.getElementsByTagName('body')[0];
  let elementToTrack = bodyElement.querySelector('.trackme');
  trackedObjPos = elementToTrack.getBoundingClientRect().top;
  if(trackedObjPos > 264)
  {
    bodyElement.style.cssText = '';
  }

Надеюсь, этот ответ стал более полезным.

2 голосов
/ 01 марта 2019

Чтобы получить общее смещение элемента, вы можете рекурсивно суммировать все родительские смещения:

function getParentOffsets(el): number {
if (el.offsetParent) {
    return el.offsetParent.offsetTop + getParentOffset(el.offsetParent);
} else {
    return 0;
}
}

с помощью этой служебной функции общее смещение верхнего элемента dom:

el.offsetTop + getParentOffsets(el);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...