web-dev-qa-db-fra.com

Comment obtenir la valeur offset (). Top d'un élément sans utiliser jQuery?

Je suis en train de programmer une application d'une seule page en utilisant le framework Angular. Je suis nouveau à cela. J'ai lu ce guide pour m'aider à comprendre les différences fondamentales entre jQuery et Angular et j'aimerais suivre ces instructions autant que possible et NE PAS utiliser jQuery.

Sauf que jQuery permet de contourner certaines des incompatibilités du navigateur et fournit une bibliothèque de fonctions utile, comme être capable de connaître la position haute d'un élément depuis le haut de la fenêtre, comme dans $('element').offset().top. Aucun Javascript simple ne semble pouvoir s'approcher sans réécrire cette fonction, à quel point ne serait-ce pas be une meilleure idée d'utiliser un jQuery ou un jQuery comme une bibliothèque?

Plus précisément, ce que j'essaie de faire est de définir une directive qui fixe un élément en place une fois que le haut de celui-ci est fait défiler à un certain emplacement de la fenêtre. Voici à quoi ça ressemble:

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

        }
    }
}

S'il y a un bien meilleur moyen d'y parvenir en Angular que je ne comprends toujours pas, je vous serais reconnaissant de me le conseiller.

39
saikofish

utilisez getBoundingClientRect si $el est l'objet DOM actuel:

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

JSFiddle

Fiddle montrera que cela aura la même valeur que le haut offset de jquery vous donnera </ strike>

Edit: comme mentionné dans les commentaires, cela ne tient pas compte du contenu défilé, voici le code utilisé par 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
        };
    }
}
59
Patrick Evans

Voici une fonction qui le fera sans 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 };
}
45
Wolverine

Il semble que vous puissiez simplement utiliser la méthode prop sur l'élément angulaire:

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

Travaille pour moi. Est-ce que quelqu'un connaît des inconvénients à cela?

10
Darren

la solution acceptée par Patrick Evans ne prend pas en compte le défilement. J'ai légèrement changé son jsfiddle pour le démontrer: 

css: ajoute une hauteur aléatoire pour s'assurer que nous avons un espace pour faire défiler

body{height:3000px;} 

js: définit une position de défilement

jQuery(window).scrollTop(100);

par conséquent, les deux valeurs rapportées diffèrent maintenant: http://jsfiddle.net/sNLMe/66/

UPDATE 14 février 2015

il y a une demande d'extraction pour l'attente jqLite, y compris sa propre méthode de décalage (en prenant en compte la position de défilement actuelle). jetez un oeil à la source si vous voulez l'implémenter vous-même: https://github.com/angular/angular.js/pull/3799/files

3
schellmax

Vous pouvez essayer l'élément [0] .scrollTop, à mon avis, cette solution est plus rapide. 

Vous avez ici un exemple plus gros - http://cvmlrobotics.blogspot.de/2013/03/angularjs-get-element-offset-position.html

1
bmazurek

Pour que Angular 2+ obtienne le décalage de l'élément actuel (this.el.nativeElement est égal à $ (this) dans 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);
    }

}
0
Combine