Как получить значение offset(). Top элемента без использования jQuery?

Я программирую одностраничное приложение, используя Angular Framework. Я новичок в этом. Я прочитал это руководство, чтобы помочь мне понять фундаментальные различия между 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, который я до сих пор не получаю, я был бы признателен за совет.

6 ответов

Решение

Использование getBoundingClientRect если $el фактический объект DOM:

var top = $el.getBoundingClientRect().top;

JSFiddle

Fiddle покажет, что получит то же значение, что и смещение вершины jquery.

Редактировать: как уже упоминалось в комментариях, это не учитывает прокручиваемый контент, ниже приведен код, который использует jQuery

https://github.com/jquery/jquery/blob/master/src/offset.js (13.05.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
        };
    }
}

Вот функция, которая сделает это без 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 };
}

Кажется, вы можете просто использовать метод prop для углового элемента:

var top = $el.prop('offsetTop');

Работает для меня. Кто-нибудь знает какие-либо недостатки этого?

Принятое Патриком Эвансом решение не учитывает прокрутку. я немного изменил его 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

Вы можете попробовать element[0].scrollTop, на мой взгляд, это решение быстрее.

Вот вам пример большего размера - http://cvmlrobotics.blogspot.de/2013/03/angularjs-get-element-offset-position.html

Для Angular 2+, чтобы получить смещение текущего элемента (this.el.nativeElement эквивалентен $(this) в jquery):

export class MyComponent implements  OnInit {

constructor(private el: ElementRef) {}

    ngOnInit() {
      //This is the important line you can use in your function in the code
      //-------------------------------------------------------------------------- 
        let offset = this.el.nativeElement.getBoundingClientRect().top;
      //--------------------------------------------------------------------------    

        console.log(offset);
    }

}
Другие вопросы по тегам