2009-08-29 3 views
80

Я хочу получить позицию элемента относительно окна браузера (окно просмотра, на котором отображается страница, а не на всю страницу). Как это можно сделать в JavaScript?Как получить верхнее положение элемента относительно окна браузера?

Большое спасибо

+2

Я думаю, что этот вопрос похож на http://stackoverflow.com/questions/211703/is-it- возможно-получить-позицию-of-div-in-browser-viewport-not-withi, которая имеет действительно хорошее решение. –

+0

@JakobRunge, это было «приятно» в 2013 году? –

+1

Рассмотрите возможность принятия решения. –

ответ

11

Edit: Добавьте код для учета скроллинга страницы.

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 - это идентификатор элемента, смещение которого вы хотите. Адаптировано из quirksmode post.

+0

Спасибо за ваш ответ, но я думаю, что вы неправильно поняли мой вопрос, я знаю, как получить верхнюю часть элемента относительно страницы, что я пытаюсь сделать, это получить позицию относительно «окна просмотра» (т. Е. Браузера окно, а не документ) –

+0

Извините, ваше использование 'viewport' меня бросило. Итак, вы говорите, что хотите учитывать браузер Chrome, т.е. панель закладок, панель местоположений и т. Д.? –

+0

Нет, просто окно, через которое вы видите страницу. Если страница прокручивается, это будет отличаться от верхней части документа, иначе они будут одинаковыми. –

1

Функция на странице this возвращает прямоугольник с координатами верхнего, левого, вертикального и поперечного элементов передаваемого элемента относительно порта просмотра браузера.

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; 
} 
4

Вы можете попробовать:

node.offsetTop - window.scrollY

Он работает на Opera с видового экрана метатеге определены.

+2

Если я правильно понимаю [документацию] (https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop), 'offsetTop' относится к ближайшему позиционированному элементу. Который, в зависимости от структуры страницы, может быть или не быть корневым элементом. –

0

Спасибо за все ответы. Кажется, у Prototype уже есть функция, которая делает это (функция page()). Просмотрев исходный код функции, я обнаружил, что он сначала вычисляет позицию смещения элемента относительно страницы (то есть вершину документа), а затем вычитает scrollTop из этого. Подробнее см. Исходный код прототипа.

+0

Хорошее решение. Вероятно, лучше всего пойти с одной из основных библиотек, поскольку они с большей вероятностью будут давать одинаковый результат в браузерах. Если вам интересно, проверьте мой ответ. Код там будет делать, но я понятия не имею, как он будет храниться в браузерах. –

173

Существующие ответы устарели. Нативный метод getBoundingClientRect() существует уже довольно давно и делает именно то, что задает вопрос. Кроме того, он поддерживается во всех браузерах (включая IE 5, кажется!)

От MDN page:

Возвращаемое значение является объектом TextRectangle, который содержит только для чтения слева, сверху, справа и снизу свойства описания рамка в пикселях с левым верхним относительно левого верхнего угла окна просмотра.

Вы можете использовать его так:

var viewportOffset = el.getBoundingClientRect(); 
// these are relative to the viewport, i.e. the window 
var top = viewportOffset.top; 
var left = viewportOffset.left; 
+2

Это может работать некорректно при использовании масштабирования браузера (Android Chrome). Решение из @rism ([см. Ниже] (http://stackoverflow.com/a/1350681/2757230)) работает в этом случае – Dmitry

+2

Хорошо для большинства случаев, но предполагает, что элемент не находится внутри встроенного iframe, не так ли? Вопрос спрашивает об относительном окне браузера. El.getBoundingClientRect() вернет относительное окно iframe, а не окно браузера. – cakidnyc

+1

Вопрос спрашивает об относительном окне браузера. –

1

Я предполагаю, что элемент, имеющий идентификатор 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); 
+0

jQuery - это JavaScript. Думаю, вы имели в виду, что «это не 100% ванили/чистый JS». _ – hungerstar

+0

Да, вот что я имел в виду. – Sunil

+0

jquery is ужасно – Tobiq

14

В моем случае, просто чтобы быть безопасными в отношении прокрутки, я добавил window.scroll к уравнению:

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

Это позволяет мне получить реальное относительное положение элемента в документе, даже если она была прокручена.

+2

Разве вы не должны добавлять положение прокрутки, а не вычитать его? –

+0

Я поддержал ответ, но все же, @lulian Onofrei прав. Пожалуйста, измените. – pmrotule

+0

@Fabio 'getBoundingClientRect(). Top' не в моем IE11, он возвращает 0. У вас есть решение. – Arif

0

Иногда getBoundingClientRect() Значение свойства объекта показывает 0 для IE. В этом случае вам нужно установить 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(); 
0

Я думаю, что JQuery на самом деле реализуется в очень изящным способом. Если вы посмотрите на источник offset, вы найдете это в основном, как они реализуют его:

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

return { 
    top: rect.top + win.pageYOffset, 
    left: rect.left + win.pageXOffset 
}; 
Смежные вопросы