如何获得一个元素's顶部位置相对于浏览器的视口?

我想获得一个元素相对于浏览器的视口(显示页面的视口,而不是整个页面)的位置。如何在JavaScript中做到这一点?

非常感谢

318253 次浏览

编辑:添加一些代码来解释页面滚动。

function findPos(id) {
var node = document.getElementById(id);
var curtop = 0;
var curtopscroll = 0;
if (node.offsetParent) {
do {
curtop += node.offsetTop;
curtopscroll += node.offsetParent ? node.offsetParent.scrollTop : 0;
} while (node = node.offsetParent);


alert(curtop - curtopscroll);
}
}

id参数是你想要偏移量的元素的id。改编自quirksmode帖子

页面上的函数将返回一个矩形,其中包含传递元素相对于浏览器视图端口的上、左、高和宽坐标。

    localToGlobal: function( _el ) {
var target = _el,
target_width = target.offsetWidth,
target_height = target.offsetHeight,
target_left = target.offsetLeft,
target_top = target.offsetTop,
gleft = 0,
gtop = 0,
rect = {};


var moonwalk = function( _parent ) {
if (!!_parent) {
gleft += _parent.offsetLeft;
gtop += _parent.offsetTop;
moonwalk( _parent.offsetParent );
} else {
return rect = {
top: target.offsetTop + gtop,
left: target.offsetLeft + gleft,
bottom: (target.offsetTop + gtop) + target_height,
right: (target.offsetLeft + gleft) + target_width
};
}
};
moonwalk( target.offsetParent );
return rect;
}

你可以试试:

node.offsetTop - window.scrollY

它在定义了视口元标签的Opera上工作。

谢谢你的回答。Prototype似乎已经有了这样一个函数(page()函数)。通过查看该函数的源代码,我发现它首先计算相对于页面的元素偏移位置(即文档顶部),然后从中减去scrollTop。更多细节请参见原型的源代码。

现有的答案现在已经过时了。本机getBoundingClientRect()方法已经存在了相当长一段时间了,它所做的正是问题所要求的。此外,所有浏览器都支持它(似乎包括IE 5 !)

MDN页面:

返回值是一个TextRectangle对象,它包含以像素为单位描述边界框的只读左、上、右和下属性,相对于viewport的左上角

你可以这样使用它:

var viewportOffset = el.getBoundingClientRect();
// these are relative to the viewport, i.e. the window
var top = viewportOffset.top;
var left = viewportOffset.left;
我假设在网页中存在一个id为btn1的元素,并且jQuery也包括在内。这适用于所有现代浏览器的Chrome, FireFox, IE >=9和Edge。 jQuery仅用于确定相对于文档的位置
var screenRelativeTop =  $("#btn1").offset().top - (window.scrollY ||
window.pageYOffset || document.body.scrollTop);


var screenRelativeLeft =  $("#btn1").offset().left - (window.scrollX ||
window.pageXOffset || document.body.scrollLeft);

在我的例子中,为了安全起见,我添加了窗口。滚动到方程式:

var element = document.getElementById('myElement');
var topPos = element.getBoundingClientRect().top + window.scrollY;
var leftPos = element.getBoundingClientRect().left + window.scrollX;

这允许我获得文档上元素的真实相对位置,即使它已经被滚动。

有时,IE的getBoundingClientRect()对象的属性值显示为0。在这种情况下,你必须为元素设置display = 'block'。您可以使用下面的代码为所有浏览器获得偏移。

扩展jQuery功能:

(function($) {
jQuery.fn.weOffset = function () {
var de = document.documentElement;
$(this).css("display", "block");
var box = $(this).get(0).getBoundingClientRect();
var top = box.top + window.pageYOffset - de.clientTop;
var left = box.left + window.pageXOffset - de.clientLeft;
return { top: top, left: left };
};
}(jQuery));

使用:

var elementOffset = $("#" + elementId).weOffset();

jQuery非常优雅地实现了这一点。如果你查看jQuery的offset的源代码,你会发现它基本上是这样实现的:

var rect = elem.getBoundingClientRect();
var win = elem.ownerDocument.defaultView;


return {
top: rect.top + win.pageYOffset,
left: rect.left + win.pageXOffset
};
var element =  document.querySelector('selector');
var bodyRect = document.body.getBoundingClientRect(),
elemRect = element.getBoundingClientRect(),
offset   = elemRect.top - bodyRect.top;
function inViewport(element) {
let bounds = element.getBoundingClientRect();
let viewWidth = document.documentElement.clientWidth;
let viewHeight = document.documentElement.clientHeight;


if (bounds['left'] < 0) return false;
if (bounds['top'] < 0) return false;
if (bounds['right'] > viewWidth) return false;
if (bounds['bottom'] > viewHeight) return false;


return true;
}

source

根据德里克的回答。

/**
* Gets element's x position relative to the visible viewport.
*/
function getAbsoluteOffsetLeft(el) {
let offset = 0;
let currentElement = el;


while (currentElement !== null) {
offset += currentElement.offsetLeft;
offset -= currentElement.scrollLeft;
currentElement = currentElement.offsetParent;
}


return offset;
}


/**
* Gets element's y position relative to the visible viewport.
*/
function getAbsoluteOffsetTop(el) {
let offset = 0;
let currentElement = el;


while (currentElement !== null) {
offset += currentElement.offsetTop;
offset -= currentElement.scrollTop;
currentElement = currentElement.offsetParent;
}


return offset;
}

这里有一些关于Angular2 +的东西。在版本13上测试

event.srcElement.getBoundingClientRect().top;