需要在Javascript中计算offsetRight

13

我需要计算DOM对象的offsetRight。我已经有了一些简单的代码来获取offsetLeft,但是没有javascript offsetRight属性。如果我将offsetLeft和offsetWidth相加,那么这样做可以吗?或者有更好的方法吗?

function getOffsetLeft(obj)
{
    if(obj == null)
        return 0;
    var offsetLeft = 0;
    var tmp = obj;
    while(tmp != null)
    {
        offsetLeft += tmp.offsetLeft;
        tmp = tmp.offsetParent;
    }
    return offsetLeft;
}

function getOffsetRight(obj)
{
    if (obj == null)
        return 0;
    var offsetRight = 0;
    var tmp = obj;
    while (tmp != null)
    {
        offsetRight += tmp.offsetLeft + tmp.offsetWidth;
        tmp = tmp.offsetParent;
    }
    return offsetRight;    
}

你想用“offsetRight”做什么?“left”和“top”的原因是窗口(或任何容器框)的顶部和左侧是固定的;视图框架的拉伸/收缩发生在右侧和底部(从概念上讲)。 - Pointy
我必须在当前对象后面绘制一个div,而且我正在使用从右到左的语言。我必须知道对象(文本)在右侧结束的位置,以便确定div的右边缘的位置。由于DOM中的所有内容都是从左到右工作的,这非常令人头疼。 - Dan Bailiff
4个回答

13

不能再更简单了:

let offsetright = window.innerWidth - obj.offsetLeft - obj.offsetWidth

3
另一种计算offsetRight的方法是 window.innerWidth - element.getBoundingClientRect().right - Hasan Sefa Ozalp
不错,但这个例子太简单了。它没有考虑到嵌套元素,例如当一些包装元素具有相对定位的样式时。它需要递归或利用视口。它也没有考虑溢出。 - Modular
@HasanSefaOzalp 我也喜欢那种方式,这正是我4年前发布的内容,但它没有考虑溢出问题。 - Modular

8

更新的帖子以澄清一些易错点:

// Assuming these variables:
const elem = document.querySelector('div'),
      body = document.body,
      html = document.documentElement;

这里有几种方法:
/* Leveraging the viewport AND accounting for possible overflow to the right */
const offsetRight = body.clientWidth - elem.getBoundingClientRect().right
// OR
const offsetRight = body.scrollWidth - elem.getBoundingClientRect().right
// OR
const offsetRight = html.scrollWidth - elem.getBoundingClientRect().right

或者

/*
*  Likely the safest option:
*  Doesn't depend on the viewport
*  Accounts for overflow to the right
*  Works even if the user is scrolled to the right some
*  NOTE: This ends at the <html> element,
*  but you may want to modify the code to end at the <body>
*/
const getOffsetRight = e => {
    let left = e.offsetWidth + e.offsetLeft;
    const traverse = eRef => {
        eRef = eRef.offsetParent; // `.offsetParent` is faster than `.parentElement`
        if (eRef) {
            left += eRef.offsetLeft;
            traverse(eRef);
        }
    };
    traverse(e);
    return html.scrollWidth - left;
};
const offsetRight = getOffsetRight(elem);

导入考虑事项:

  • 您是否为所有元素使用了box-sizing: border-box;
  • 是否设置了margin-left在您需要考虑的<body><html>元素上?
  • <body>是否具有固定宽度,但是通过margin: 0 auto;居中对齐?

这些内容将有助于确定要使用哪种方法以及是否要修改CSS和/或JavaScript以考虑这些用例。

ORIGINAL POST:

A few choices:

  • If you want "offsetRight" relative to the viewport, use element.getBoundingClientRect().right;

  • Your example is good simply subracting the parent width from the element's width + offsetLeft.

  • Lastly, to be relative to the document, and to speed up traversing (offsetParent):

In this example, I'm positioning a pseudo dropdown element below the referenced element, but because I'm avoiding some tricky z-index issues and want to have the element be referenced from the right and expand out left, I had to append it to the body element, and the get the "offsetRight" from the original parent.

...

// Set helper defaults
dropdownElem.style.left = 'auto';
dropdownElem.style.zIndex = '10';

// Get the elem and its offsetParent
let elem = dropdownElemContainer;
let elemOffsetParent = elem.offsetParent;

// Cache widths
let elemWidth = elem.offsetWidth;
let elemOffsetParentWidth = 0;

// Set the initial offsets
let top = elem.offsetHeight; // Because I want to visually append the elem at the bottom of the referenced bottom
let right = 0;

// Loop up the DOM getting the offsetParent elements so you don't have to traverse the entire ancestor tree
while (elemOffsetParent) {
  top += elem.offsetTop;
  elemOffsetParentWidth = elemOffsetParent.offsetWidth;
  right += elemOffsetParentWidth - (elem.offsetLeft + elemWidth); // Most important line like your own example
  // Move up the DOM
  elem = elemOffsetParent;
  elemOffsetParent = elemOffsetParent.offsetParent;
  elemWidth = elemOffsetParentWidth;
}

// Set the position and show the elem
dropdownElem.style.top = top + 'px';
dropdownElem.style.right = right + 'px';
dropdownElem.style.display = 'block';

3
//Object references
function getObject(id) {
   var object = null;
   if (document.layers) {
    object = document.layers[id];
   } else if (document.all) {
    object = document.all[id];
   } else if (document.getElementById) {
    object = document.getElementById(id);
   }
   return object;
}
//Get pixel dimensions of screen
function getDimensions(){
    var winW = 630, winH = 460;
    if (document.body && document.body.offsetWidth) {
     winW = document.body.offsetWidth;
     winH = document.body.offsetHeight;
    }
    if (document.compatMode=='CSS1Compat' && document.documentElement && document.documentElement.offsetWidth ) {
     winW = document.documentElement.offsetWidth;
     winH = document.documentElement.offsetHeight;
    }
    if (window.innerWidth && window.innerHeight) {
     winW = window.innerWidth;
     winH = window.innerHeight;
    }
    return{"width":winW, "height":winH}
}
//Get the location of element
function getOffsetRight(elem){
    element=getObject(elem)
    var width = element.offsetWidth
    var right = 0;
    while (element.offsetParent) { 
        right += element.offsetLeft; 
        element = element.offsetParent;
    }
    right += element.offsetLeft;
    right = getDimensions()["width"]-right
    right -= width
    return right
}

这并不是百分之百可靠的方式,但通常你可以通过调用getOffsetRight("[object.id]")来获取"offsetRight"。


0

2
这只是另一种做offsetLeft已经做过的事情的方式,仍然不能给我offsetRight。这有什么用? - Dan Bailiff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接