Lecture de la documentation AngularJS Je ne sais pas si $anchorScroll
peut avoir une option de durée/accélération pour un défilement régulier des éléments.
Il dit seulement:
$location.hash('bottom');
// call $anchorScroll()
$anchorScroll();
Je n'utilise pas jquery et je ne veux pas; existe-t-il encore un moyen simple mais intelligent de créer ou d'étendre $anchorScroll
afin de rendre le défilement plus fluide?
Malheureusement, ceci n'est pas possible avec $anchorScroll
. Comme vous l'avez découvert, $anchorScroll
n'a pas d'options et ne fonctionne pas avec $ngAnimate
. Pour animer le parchemin, vous devez utiliser votre propre service/usine ou simplement du javascript.
Par souci d’auto-apprentissage, j’ai rassemblé un exemple avec un service de défilement régulier. Il y a probablement de meilleures façons de le faire, donc tout retour d'information est encouragé.
Pour faire défiler un élément, vous associez un ng-click="gotoElement(ID)"
à un élément. Je pense qu'une solution encore meilleure serait d'en faire une directive.
Voici le exemple de travail sur jsFiddle .
Mettre à jour
Il existe maintenant un certain nombre de directives de tiers pour accomplir cela.
Vous pouvez également utiliser le lien angular-scroll, " https://github.com/dured/angular-scroll/ ". Il s'agit d'un défilement régulier et de quelques fonctions d'assouplissement permettant d'obtenir un aspect professionnel.
La réponse de Brett a très bien fonctionné pour moi. J'ai apporté quelques modifications mineures à sa solution en termes de modularisation et de testabilité.
Voici encore un autre exemple de travail sur JsFiddle qui inclut l’autre version avec les tests inclus.
Pour tester, j'utilise Karma et Jasmine. La signature a été légèrement modifiée comme suit:
anchorSmoothScroll.scrollTo(elementId, speed);
Où element est un attribut obligatoire auquel faire défiler et où speed est facultatif, la valeur par défaut étant 20 (comme auparavant).
Vous pouvez également utiliser ngSmoothScroll, link: https://github.com/d-oliveros/ngSmoothScroll .
Incluez simplement le module smoothScroll
comme dépendance et utilisez-le comme ceci:
<a href="#" scroll-to="my-element-3">Click me!</a>
Aucune des solutions ici ne fait réellement ce que l'OP a demandé à l'origine, à savoir, faire défiler $anchorScroll
en douceur. La différence entre les directives de défilement régulier et $anchroScroll
réside dans le fait qu’il utilise/modifie $location.hash()
, ce qui peut être souhaitable dans certains cas.
Voici Gist pour le module simple qui remplace le défilement $ anchorScroll par le défilement régulier. Il utilise https://github.com/oblador/angular-scroll bibliothèque pour le défilement lui-même (remplacez-le par autre chose si vous voulez, cela devrait être facile).
https://Gist.github.com/mdvorak/fc8b531d3e082f3fdaa9
Note: En réalité, $ anchorScroll ne défile pas en douceur, mais il remplace son gestionnaire pour le défilement.
Activez-le simplement en référençant le module mdvorakSmoothScroll
de votre application.
Je ne sais pas comment animer $anchorScroll
. Voici comment je le fais dans mes projets:
/* Scroll to top on each ui-router state change */
$rootScope.$on('$stateChangeStart', function() {
scrollToTop();
});
Et la fonction JS:
function scrollToTop() {
if (typeof jQuery == 'undefined') {
return window.scrollTo(0,0);
} else {
var body = $('html, body');
body.animate({scrollTop:0}, '600', 'swing');
}
log("scrollToTop");
return true;
}
Alan, merci. Si cela intéresse quelqu'un, je l'ai formaté en fonction des normes John Pappa.
(function() {
'use strict';
var moduleId = 'common';
var serviceId = 'anchorSmoothScroll';
angular
.module(moduleId)
.service(serviceId, anchorSmoothScroll);
anchorSmoothScroll.$inject = ['$document', '$window'];
function anchorSmoothScroll($document, $window) {
var document = $document[0];
var window = $window;
var service = {
scrollDown: scrollDown,
scrollUp: scrollUp,
scrollTo: scrollTo,
scrollToTop: scrollToTop
};
return service;
function getCurrentPagePosition(currentWindow, doc) {
// Firefox, Chrome, Opera, Safari
if (currentWindow.pageYOffset) return currentWindow.pageYOffset;
// Internet Explorer 6 - standards mode
if (doc.documentElement && doc.documentElement.scrollTop)
return doc.documentElement.scrollTop;
// Internet Explorer 6, 7 and 8
if (doc.body.scrollTop) return doc.body.scrollTop;
return 0;
}
function getElementY(doc, element) {
var y = element.offsetTop;
var node = element;
while (node.offsetParent && node.offsetParent !== doc.body) {
node = node.offsetParent;
y += node.offsetTop;
}
return y;
}
function scrollDown(startY, stopY, speed, distance) {
var timer = 0;
var step = Math.round(distance / 25);
var leapY = startY + step;
for (var i = startY; i < stopY; i += step) {
setTimeout('window.scrollTo(0, ' + leapY + ')', timer * speed);
leapY += step;
if (leapY > stopY) leapY = stopY;
timer++;
}
};
function scrollUp(startY, stopY, speed, distance) {
var timer = 0;
var step = Math.round(distance / 25);
var leapY = startY - step;
for (var i = startY; i > stopY; i -= step) {
setTimeout('window.scrollTo(0, ' + leapY + ')', timer * speed);
leapY -= step;
if (leapY < stopY) leapY = stopY;
timer++;
}
};
function scrollToTop(stopY) {
scrollTo(0, stopY);
};
function scrollTo(elementId, speed) {
var element = document.getElementById(elementId);
if (element) {
var startY = getCurrentPagePosition(window, document);
var stopY = getElementY(document, element);
var distance = stopY > startY ? stopY - startY : startY - stopY;
if (distance < 100) {
this.scrollToTop(stopY);
} else {
var defaultSpeed = Math.round(distance / 100);
speed = speed || (defaultSpeed > 20 ? 20 : defaultSpeed);
if (stopY > startY) {
this.scrollDown(startY, stopY, speed, distance);
} else {
this.scrollUp(startY, stopY, speed, distance);
}
}
}
};
};
})();