Как получить значение offset(). Верхнее значение элемента без использования jQuery?
Я программирую одностраничное приложение, используя структуру Angular. Я новичок в этом. Я прочитал это руководство, чтобы помочь мне понять фундаментальные различия между jQuery и Angular, и я хотел бы как можно больше следовать этому руководству и НЕ использовать jQuery.
За исключением того, что jQuery помогает обойти некоторые несовместимости браузера и предоставляет полезную библиотеку функций, например, возможность узнать верхнее положение элемента сверху окна, как в $('element').offset().top
. Нет простого Javascript, похоже, можно подойти вплотную, не переписывая эту функцию, и в этот момент не лучше ли использовать библиотеку jQuery или jQuery?
В частности, то, что я пытаюсь сделать, это настроить директиву, которая фиксирует элемент на месте, когда верхняя часть его прокручивается до определенной позиции в окне. Вот как это выглядит:
directives.scrollfix = function () {
return {
restrict: 'C',
link: function (scope, element, $window) {
var $page = angular.element(window)
var $el = element[0]
var elScrollTopOriginal = $($el).offset().top - 40
$page.bind('scroll', function () {
var windowScrollTop = $page[0].pageYOffset
var elScrollTop = $($el).offset().top
if ( windowScrollTop > elScrollTop - 40) {
elScrollTopOriginal = elScrollTop - 40
element.css('position', 'fixed').css('top', '40px').css('margin-left', '3px');
}
else if ( windowScrollTop < elScrollTopOriginal) {
element.css('position', 'relative').css('top', '0').css('margin-left', '0');
}
})
}
}
}
Если в Angular есть гораздо лучший способ достичь этого, чего я еще не получаю, я буду благодарен за совет.
Ответы
Ответ 1
используйте getBoundingClientRect
, если $el
- это фактический объект DOM:
var top = $el.getBoundingClientRect().top;
JSFiddle
Fiddle покажет, что это получит то же значение, что и верхняя строка jquery offset даст вам
Изменить: как указано в комментариях, это не учитывает прокручиваемый контент, ниже приведен код, который jQuery использует
https://github.com/jquery/jquery/blob/master/src/offset.js (5/13/2015)
offset: function( options ) {
//...
var docElem, win, rect, doc,
elem = this[ 0 ];
if ( !elem ) {
return;
}
rect = elem.getBoundingClientRect();
// Make sure element is not hidden (display: none) or disconnected
if ( rect.width || rect.height || elem.getClientRects().length ) {
doc = elem.ownerDocument;
win = getWindow( doc );
docElem = doc.documentElement;
return {
top: rect.top + win.pageYOffset - docElem.clientTop,
left: rect.left + win.pageXOffset - docElem.clientLeft
};
}
}
Ответ 2
Вот функция, которая сделает это без jQuery:
function getElementOffset(element)
{
var de = document.documentElement;
var box = element.getBoundingClientRect();
var top = box.top + window.pageYOffset - de.clientTop;
var left = box.left + window.pageXOffset - de.clientLeft;
return { top: top, left: left };
}
Ответ 3
Кажется, вы можете просто использовать метод prop в элементе angular:
var top = $el.prop('offsetTop');
Работает для меня. Кто-нибудь знает какие-то недостатки?
Ответ 4
принятое решение Патрика Эванса не учитывает прокрутки.
я немного изменил его jsfiddle, чтобы продемонстрировать это:
css: добавьте некоторую произвольную высоту, чтобы убедиться, что у нас есть свободное пространство для прокрутки
body{height:3000px;}
js: установите некоторую позицию прокрутки
jQuery(window).scrollTop(100);
в результате, два сообщенных значения теперь отличаются: http://jsfiddle.net/sNLMe/66/
ОБНОВЛЕНИЕ 14 февраля 2015 г.
есть запрос на растяжение для ожидания jqLite, включая его собственный метод смещения (позаботится о текущей позиции прокрутки). посмотрите на источник, если вы хотите его реализовать самостоятельно: https://github.com/angular/angular.js/pull/3799/files
Ответ 5
Вы можете попробовать элемент [0].scrollTop, на мой взгляд это решение быстрее.
Здесь у вас есть больший пример - http://cvmlrobotics.blogspot.de/2013/03/angularjs-get-element-offset-position.html