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.
utilisez getBoundingClientRect
si $el
est l'objet DOM actuel:
var top = $el.getBoundingClientRect().top;
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
};
}
}
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 };
}
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?
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
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
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);
}
}