Ответ 1
Вы всегда можете рассчитать смещение, факторинг в позиции прокрутки:
var offset_t = $(selector).offset().top - $(window).scrollTop();
var offset_l = $(selector).offset().left - $(window).scrollLeft();
var offset = $(selector).offset();
Значения переменной смещения изменяются, если мы прокручиваем страницу вверх и вниз, я хочу точные и фиксированные значения смещения, сохраняя позицию "селектора" по умолчанию (статический). Как я могу это сделать?
Вы всегда можете рассчитать смещение, факторинг в позиции прокрутки:
var offset_t = $(selector).offset().top - $(window).scrollTop();
var offset_l = $(selector).offset().left - $(window).scrollLeft();
Просто хотел добавить свой ответ здесь, после того, как у вас были такие же проблемы:
После получения описанного выше поведения Я посмотрел документацию jQuery и обнаружил, что
jQuery не поддерживает получение смещенных координат элементов скрытых или учет границ, полей или отступов, установленных в элементе body.
Элемент, который я пытался получить смещение, на самом деле был установлен на display:none;
, что дало мне ложное смещение, которое изменилось при прокрутке (даже если элемент не двигался).
Поэтому убедитесь, что вы не пытаетесь получить смещение скрытого элемента! надеюсь, это поможет кому-то:)
Еще одна потенциальная причина - если ваш <body>
имеет CSS, который устанавливает overflow-x: hidden;
- полностью разрушает метод jQuery offset()
.
В этом случае $(window).scrollTop()
всегда равно 0, поэтому принятый ответ не работает.
У меня была очень похожая проблема с исходным вопросом. Смещение непросто. Надеюсь, это поможет решить ваши проблемы, как и мои. У меня есть 3 JSFiddles, чтобы продемонстрировать.
offset().top
вашего элемента div из окна, вы всегда получите статическое число (т.е. если $(window)
- это свиток, и у вас есть div внутри окна с offset().top
применяется div всегда будет иметь статическое число). Это смещение - точное количество пикселей, которое элемент существует из верхней части $(window)
, независимо от того, насколько далеко вы прокручиваете его. Для каждого из моих JSFiddles я посмотрю, как далеко от объекта $('div#offset')
находится верхняя часть его прокручиваемого контейнера. В этом первом примере обратите внимание на то, как число не изменяется:https://jsfiddle.net/BrianIsSecond/ehkgh2gu/
$(window)
- это не тот контейнер, который прокручивается. Вместо этого вы создаете div, у которого есть "переполнение-y: прокрутка"; набор атрибутов. В этом случае $('div#offset').offset().top
действует совсем иначе, чем предыдущий пример. Вы заметите, что это изменится при прокрутке. Для моего примера JSFiddle я просто завернул все в div#overflow
, у которого установлен атрибут overflow-y:scroll;
. Пример:https://jsfiddle.net/BrianIsSecond/tcs390h6/ < --- Обратите внимание, что переполнение div # не на 100%. Я сделал 100px меньше 100%. Я использую это, чтобы проиллюстрировать легкую ошибку, о которой я расскажу ниже.
$('#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/
В конечном счете то, что вы ищете, выглядит примерно так:
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): Я создал функцию, помогающую решить эту проблему. Наслаждайтесь!
/*
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;
}
}
В 2015 году "правильный" ответ больше не должен использоваться - смещение было изменено. Любой код, который использовал вышеупомянутое решение, больше не будет работать должным образом.
Решение: обновите jquery до более новой версии (работает в 1.11.3). Или... измените .offset вызов вместо использования .position.