通过滚动页面更改 jquery 偏移值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10297688/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 09:06:13  来源:igfitidea点击:

jquery offset values changes by scrolling the page

jquery

提问by Gaurav

var offset = $(selector).offset();

The values of offset variable changes if we scroll the page up and down, i want the exact and fixed offset values while keeping the position of the "selector" default(static).How can i do this?

如果我们上下滚动页面,偏移变量的值会发生变化,我想要精确和固定的偏移值,同时保持“选择器”的位置默认(静态)。我该怎么做?

回答by trickyzter

You could always calculate the offset, factoring in the scroll position:

您总是可以计算偏移量,将滚动位置考虑在内:

var offset_t = $(selector).offset().top - $(window).scrollTop();
var offset_l = $(selector).offset().left - $(window).scrollLeft();

回答by m.t.bennett

Just wanted to add my answer here after having the same issues:

在遇到相同的问题后,只想在这里添加我的答案:

After getting the behaviour described above I looked at the jQuery documentationand discovered that

在获得上述行为后,我查看了 jQuery 文档并发现

jQuery does not support getting the offset coordinates of hiddenelements or accounting for borders, margins, or padding set on the body element.

jQuery 不支持获取隐藏元素的偏移坐标,也不支持在 body 元素上设置边框、边距或填充。

The element I was trying to get the offset of was in fact set to display:none;giving me a false offset which changed when scrolling (even though the element didn't move).

我试图获取偏移量的元素实际上设置为display:none;给我一个错误的偏移量,该偏移量在滚动时发生了变化(即使元素没有移动)。

So make sure you're not trying to get an offset of a hidden element! hope this helps someone :)

因此,请确保您没有尝试获取隐藏元素的偏移量!希望这对某人有所帮助:)

回答by Nathan Friedly

One other potential cause is if your <body>happens to have CSS that sets overflow-x: hidden;- that completely breaks jQuery's offset()method.

另一个潜在原因是,如果您<body>碰巧设置了 CSS overflow-x: hidden;- 这完全破坏了 jQuery 的offset()方法。

In that case, $(window).scrollTop()is always 0, so the accepted answer does not work.

在这种情况下,$(window).scrollTop()始终为 0,因此接受的答案不起作用。

回答by Brian

I had a very similar issue to the original question. The offset is kinda tricky. Hopefully, this will help solve your problems as it did mine. I have 3 JSFiddles to demonstrate.

我有一个与原始问题非常相似的问题。偏移有点棘手。希望这将有助于解决您的问题,就像我的问题一样。我有 3 个 JSFiddles 来演示。

  1. If you are basing the offset().topof your div element from the window, you will always get a static number (i.e. if the $(window)is the thing that scrolls and you have a div inside the window with offset().topapplied, the div will always have a static number). This offset is the exact number of pixels the element exists from the top of the $(window)no matter how far down you scroll. For each of my JSFiddles, I'll see how far down the object $('div#offset')is from the top of it's scrolling container. In this first example, notice how the number doesn't change:
  1. 如果您将offset().topdiv 元素作为窗口的基础,您将始终获得一个静态数字(即,如果$(window)div 是滚动的东西并且您在应用了窗口内offset().top的 div,则该 div 将始终具有一个静态数字)。$(window)无论您向下滚动多远,此偏移量都是元素距顶部的确切像素数。对于我的每个 JSFiddles,我会看到对象$('div#offset')离它的滚动容器顶部有多远。在第一个示例中,请注意数字是如何不变的:

https://jsfiddle.net/BrianIsSecond/ehkgh2gu/

https://jsfiddle.net/BrianIsSecond/ehkgh2gu/

  1. Now, lets say that the $(window)isn't the container that scrolls. You instead create a div that has an "overflow-y:scroll;" attribute set. In this case, the $('div#offset').offset().topacts very differently than the previous example. You'll notice it changes as you scroll. For my JSFiddle example, I simply wrapped everything in div#overflowthat has overflow-y:scroll;attribute set. See example:
  1. 现在,让我们说这$(window)不是滚动的容器。您改为创建一个具有“溢出-y:滚动;”的 div。属性集。在这种情况下,其$('div#offset').offset().top行为与前一个示例非常不同。当您滚动时,您会注意到它发生了变化。对于我的 JSFiddle 示例,我只是将所有内容都包含在div#overflow具有overflow-y:scroll;属性集的内容中。见示例:

https://jsfiddle.net/BrianIsSecond/tcs390h6/<--- Note too that div#overflow isn't 100% tall. I made it 100px short of 100%. I am using that to illustrate an easy mistake, which I will address next.

https://jsfiddle.net/BrianIsSecond/tcs390h6/<--- 还要注意 div#overflow 不是 100% 高。我使它比 100% 少了 100px。我用它来说明一个简单的错误,我将在接下来解决这个错误。

  1. If your like me, example 2 isn't what you were wanting. The best solution I have found is to grab $('#overflow').scrollTop()and add it to $('#offset').offset().top(i.e. var ep = $('#offset').offset().top + $('#overflow').scrollTop()). Basically, by adding these two changing numbers together, they 'sorta' cancel each other out, giving you the exact position of the div#offsetelement... or do they? Well, this is where the position of the div#overflowis important! You must, must, must take into account the position of the scrollable container. To do this, take $('#overflow').offset().topand subtract it from $('#offset').offset().topbefore you add $('#overflow').scrollTop(). This will then factor in the position of the scrollable container from the window. See example:
  1. 如果您喜欢我,示例 2 不是您想要的。我发现的最佳解决方案是抓取$('#overflow').scrollTop()并将其添加到$('#offset').offset().top(即var ep = $('#offset').offset().top + $('#overflow').scrollTop())。基本上,通过将这两个不断变化的数字相加,它们“差不多”会相互抵消,从而为您提供div#offset元素的确切位置……还是这样?嗯,这就是位置div#overflow很重要的地方!您必须,必须,必须考虑可滚动容器的位置。要做到这一点,需要$('#overflow').offset().top从减去它$('#offset').offset().top添加之前$('#overflow').scrollTop()。然后,这将考虑可滚动容器在窗口中的位置。见示例:

https://jsfiddle.net/BrianIsSecond/yzc5ycyg/

https://jsfiddle.net/BrianIsSecond/yzc5ycyg/

Ultimately, what you are looking for is something like this:

最终,您正在寻找的是这样的:

var w = $('#overflow'),   // overflow-y:scroll;
    e = $('#offset');     // element

$('#overflow').scroll(function(){
    var wh = w.height(),                             // window height
        sp = w.scrollTop(),                          // scroll position
        ep = (e.offset().top - w.offset().top) + sp; // element position

    console.log(ep);
});


UPDATE (10/11/17): I've created a function to help solve this problem. Enjoy!

更新 (10/11/17):我创建了一个函数来帮助解决这个问题。享受!

/*
function: betterOffset
hint: Allows you to calculate dynamic and static offset whether they are in a div container with overscroll or not.

            name:           type:               option:         notes:
@param      s (static)      boolean             required        default: true | set false for dynamic
@param      e (element)     string or object    required
@param      v (viewer)      string or object    optional        If you leave this out, it will use $(window) by default. What I am calling the 'viewer' is the thing that scrolls (i.e. The element with "overflow-y:scroll;" style.).

@return                  numeric
*/
function betterOffset(s, e, v) {
    // Set Defaults
        s = (typeof s == 'boolean') ? s : true;
        e = (typeof e == 'object') ? e : $(e);
        if (v != undefined) {v = (typeof v == 'object') ? v : $(v);} else {v = null;}

    // Set Variables
        var w = $(window),              // window object
            wp = w.scrollTop(),         // window position
            eo = e.offset().top;        // element offset
        if (v) {
            var vo = v.offset().top,    // viewer offset
                vp = v.scrollTop();     // viewer position
        }

    // Calculate
        if (s) {
            return (v) ? (eo - vo) + vp : eo;
        } else {
            return (v) ? eo - vo : eo - wp;
        }
}

回答by mayank mandloi

I am having the same problem while editing a old website the workaround I find out is to use $(selector)[0].offsetTopinstead of $(selector).offset().top and it is working fine for me right now.

我在编辑旧网站时遇到了同样的问题,我发现的解决方法是使用$(selector)[0].offsetTop而不是 $(selector).offset().top ,它现在对我来说很好用。

回答by Cymbals

In 2015, the 'correct' answer should no longer be used - offset has been modified. Any code that used the above solution will no longer work properly.

2015 年,不应再使用“正确”答案 - 已修改偏移量。使用上述解决方案的任何代码将不再正常工作。

Solution: Please upgrade jquery to a newer version (works in 1.11.3). Or... change .offset call to use .position instead.

解决方案:请将 jquery 升级到较新的版本(适用于 1.11.3)。或者...更改 .offset 调用以使用 .position 代替。