2013-09-23 14 views
36

Programuję aplikację jednostronicową, korzystając z frameworka Angular. Jestem na to nowy. Przeczytałem this guide, aby pomóc mi zrozumieć podstawowe różnice między jQuery i Angular i chciałbym postępować zgodnie z tymi wskazówkami w jak największym stopniu, a NIE używać jQuery.Jak uzyskać offset(). Najwyższa wartość elementu bez użycia jQuery?

Poza tym jQuery pomaga ominąć niektóre z niezgodności przeglądarek i zapewnia przydatną bibliotekę funkcji, takich jak możliwość poznania górnej pozycji elementu od góry okna, jak w przypadku $('element').offset().top. Żadna prosta JavaScript nie jest w stanie zbliżyć się bez przepisywania tej funkcji. W takim razie nie byłoby lepszym pomysłem użycie biblioteki jQuery lub jQuery?

W szczególności próbuję ustawić dyrektywę, która naprawia element w miejscu, gdy jego górna część przewinie się do określonej pozycji w oknie. Oto jak to wygląda:

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'); 
       } 
      }) 

     } 
    } 
} 

Jeśli jest to znacznie lepszy sposób na osiągnięcie tego w kątowa, że ​​nadal jestem po prostu nie dostanę, będę docenić porady.

+0

przyjętego rozwiązania nie bierze aktualną pozycję przewijania pod uwagę, zobacz moją odpowiedź poniżej – schellmax

Odpowiedz

55

użycie getBoundingClientRect jeśli $el jest rzeczywisty obiekt DOM:

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

JSFiddle

Fiddle pokaże, że to dostanie taką samą wartość, że jQuery offset top daje

Edytuj: jak wspomniano w komentarzach, nie uwzględnia to przewijanej treści, poniżej znajduje się kod th w jQuery używa

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 
     }; 
    } 
} 
+1

Wygląda na krzyżu zgodności przeglądarki na to jest wielki także. Dzięki. – saikofish

+4

Zauważ, że to rozwiązanie nie uwzględnia aktualnej pozycji przewijania, zobacz moją odpowiedź poniżej: – schellmax

+0

Znalazłem naprawdę prosty poniżej ... – Darren

3

przyjętego rozwiązania Patrick Evans nie bierze pod uwagę przewijania. ja już nieco zmienił swoje jsfiddle potwierdzającą ten fakt:

css: dodać trochę losowych wysokość, aby upewnić się, mamy trochę miejsca do przewijania

body{height:3000px;} 

JS: ustawić jakąś pozycję przewijania

jQuery(window).scrollTop(100); 

w wyniku czego dwie zgłoszone wartości różnią się teraz: http://jsfiddle.net/sNLMe/66/

UPDATE 14 lutego 2015

Występuje żądanie pobrania dla oczekiwania jqLite, łącznie z własną metodą przesunięcia (dbanie o aktualną pozycję przewijania). spójrz na źródło w przypadku, gdy chcesz je zaimplementować samodzielnie: https://github.com/angular/angular.js/pull/3799/files

+0

Link cvmlrobotics nie działa. – user2602152

+0

@ user2602152 dzięki za komentarz, zastąpiłem martwy link przez dodatkowe informacje, które niedawno znalazłem. – schellmax

10

wydaje się można po prostu użyć metody prop na elemencie kątowym:

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

pracuje dla mnie. Czy ktoś wie jakikolwiek minus tego?

+0

Kiedy dodaję element do DOM z elementem.prepend(); offsetTop i Left są zawsze 0. Jednak w inspektorze elementów nie jest 0. –

+0

Właściwość offsetTop zwraca tylko odsunięcie względem elementu nadrzędnego elementu (https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop), a nie do całego dokumentu, jak jQuery's offset() (http://api.jquery.com/offset/) robi. – gluecksmelodie

+0

To jest trochę rigamarole w przypadkach, gdy element DOM jest ładowany asynchronicznie, gdy funkcja wyszukuje $ el w pierwszym przejściu przez podsumowanie. W połączeniu z rozwiązaniem dostarczonym przez Darrena - musiałem najpierw użyć zwykłego JS querySelector, owinąć go w element kątowy, a następnie był w stanie wywołać rekwizyt. – vars

42

Oto funkcja, która zrobi to bez 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 }; 
} 
+0

Ponowne odkrywanie koła (a nie uniwersalnego, nawiasem mówiąc) jest zdecydowanie lepsze niż używanie "raka", tak, pewnie ... – Regent

+14

@Regent Nie każdy chce włączyć gigantyczną bibliotekę do zrobienia czegoś można to zrobić w 5 liniach kodu. – Wolverine

+0

Na przykład jquery-2.1.3.min.js (83KB) nie jest gigantycznym plikiem. A co z projektami (nie _AngularJS_), gdzie _jQuery_ jest używany w wielu miejscach? Czy sugerujesz napisanie swoich funkcji, aby kod (który działa z DOM) był krótszy? Nie sprawdzone, z błędami, bez dobrego przeglądania stron internetowych? Rozumiem, że _jQuery_ nie powinno być używane we wszystkich projektach, ale obrażając _jQuery_, stwierdzasz, że nie powinno być używane w dowolnym miejscu (a to jest niewłaściwe stwierdzenie, nawiasem mówiąc), czyż nie? – Regent

Powiązane problemy