我想知道如何在JavaScript中获取img和div等HTML元素的X和Y位置。


当前回答

更新:

递归方法(在我以前的答案中)创建了许多调用堆栈。在这种情况下,我们可以使用while循环来避免递归:

/**
 *
 * @param {HTMLElement} el
 * @return {{top: number, left: number}}
 */
function getDocumentOffsetPosition(el) {
    let top = 0, left = 0;
    while (el !== null) {
        top += el.offsetTop;
        left += el.offsetLeft;
        el = el.offsetParent;
    }
    return {top, left};
}

旧答案:

/**
 *
 * @param {HTMLElement} el
 * @return {{top: number, left: number}}
 */
function getDocumentOffsetPosition(el) {
    var position = {
        top: el.offsetTop,
        left: el.offsetLeft
    };
    if (el.offsetParent) {
        var parentPosition = getDocumentOffsetPosition(el.offsetParent);
        position.top += parentPosition.top;
        position.left += parentPosition.left;
    }
    return position;
}

感谢Thinkingtiff的回答,这只是另一个版本。

其他回答

jQuery.offset()将获取第一个元素的当前坐标,或者设置匹配元素集合中每个元素相对于文档的坐标。

这是一个使用vanilla JS递归迭代element.offsetTop和element.ooffsetParent的现代1行代码:

功能:

getTop = el => el.offsetTop + (el.offsetParent && getTop(el.offsetParent))

用法:

const el = document.querySelector('#div_id');
const elTop = getTop(el)

优势:

无论当前滚动位置如何,始终返回绝对垂直偏移。


传统语法:

function getTop(el) {
  return el.offsetTop + (el.offsetParent && getTop(el.offsetParent));
}

小与小的区别

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

我接受了@meouw的回答,添加到允许边界的clientLeft中,然后创建了三个版本:

getAbsoluteOffsetFromBody-类似于@meouw,它获取相对于文档的body或html元素的绝对位置(取决于quicks模式)

getAbsoluteOffsetFromGivenElement-返回相对于给定元素的绝对位置(relativeEl)。注意,给定的元素必须包含元素el,否则其行为将与getAbsoluteOffsetFromBody相同。如果在另一个(已知)元素中包含两个元素(可选地,节点树上的多个节点),并且希望使它们处于相同的位置,则这非常有用。

getAbsoluteOffsetFromRelative-返回相对于具有position:relative的第一个父元素的绝对位置。这与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中至少有一段有问题的代码,假设浏览器运行正常,这段代码应该是不错的,但根本没有测试其他代码。

如果您只想在javascript中完成,这里有一些使用getBoundingClientRect()的单行程序

window.scrollY + document.querySelector('#elementId').getBoundingClientRect().top // Y

window.scrollX + document.querySelector('#elementId').getBoundingClientRect().left // X

第一行将返回offsetTop,比如相对于文档的Y。第二行将返回offsetLeft,比如相对于文档的X。

getBoundingClientRect()是一个javascript函数,它返回元素相对于窗口视口的位置。