【问题标题】:Using jquery to get element's position relative to viewport使用 jquery 获取元素相对于视口的位置
【发布时间】:2009-10-14 16:05:49
【问题描述】:

获取页面上元素相对于视口(而不是文档)的位置的正确方法是什么。 jQuery.offset 功能看起来很有希望:

获取第一个元素的当前坐标,或者设置 匹配元素集合中每个元素的相对坐标 到文档。

但这与文档有关。是否有一个等效的方法可以返回相对于视口的偏移量?

【问题讨论】:

  • 注意:见@Igor G 的回答...
  • 对于 DA,您真的应该将 Igor G 的答案设置为已接受,这是救命稻草!

标签: javascript jquery position viewport offset


【解决方案1】:

确定元素大小和位置的最简单方法是调用它的 getBoundingClientRect() 方法。此方法返回视口坐标中的元素位置。它不需要参数并返回一个对象 属性 left、right、topbottom。 left 和 top 属性给出 X 和 Y 元素左上角的坐标以及right和bottom属性 给出右下角的坐标。

element.getBoundingClientRect(); // Get position in viewport coordinates

到处都支持。

【讨论】:

  • 令人难以置信的是这个方法是 IE5 加入的……好东西就是好东西!
  • 起初这看起来很棒,但它并没有考虑到用户在 Mobile Safari 7 上的缩放。
  • 最新版firefox不支持getBoundingClientRect is not a function
  • @user007 我确认它受最新的 Firefox 支持。
  • 很好的答案,让 jquery 简单地这样做:$('#myElement')[0].getBoundingClientRect().top(或任何其他职位)
【解决方案2】:

这里有两个函数可以在不使用(膨胀的)尺寸插件的情况下获取页面高度和滚动量(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
}

【讨论】:

【解决方案3】:

查看Dimensions 插件,特别是scrollTop()/scrollLeft()。信息可以在http://api.jquery.com/scrollTop找到。

【讨论】:

  • 我不想使用其他插件,但 $(window).scrollTop() 正是我所需要的!谢谢!
  • 维度插件现在是 jQuery 核心的一部分。 ViewPort 插件也很有用:appelsiini.net/projects/viewport
【解决方案4】:

jQuery.offset 需要与scrollTopscrollLeft 组合,如下图所示:

演示:

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>

【讨论】:

  • 这对我很有用,但我用它来确定工具提示是否越界,所以我修改为包含底部和右侧值:jsfiddle.net/EY6Rk/21
  • 这是绝对正确的答案。所有其他的都有问题,具体取决于鼠标/滚动增量配置、浏览器、obj 位置等。
【解决方案5】:

这是一个计算视口中元素当前位置的函数:

/**
 * 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>

【讨论】:

    【解决方案6】:

    我发现截至 2014 年 1 月,cballou 的答案在 Firefox 中不再有效。具体来说,如果客户端向右滚动而不是向下滚动,if (self.pageYOffset) 不会触发 - 因为0 是一个虚假数字.由于 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 中测试和工作。几乎可以肯定,它们都适用于所有旧版本。

    【讨论】:

      猜你喜欢
      • 2011-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-25
      • 2010-11-23
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      相关资源
      最近更新 更多