javascript - bottom - angularjs scroll to top
AngularJS-$ anchorScroll suave/duraciĆ³n (7)
Lectura de los documentos de AngularJS No he descubierto si $anchorScroll
puede tener una opción de duración / aceleración para suavizar el desplazamiento a los elementos.
Solo dice:
$location.hash(''bottom'');
// call $anchorScroll()
$anchorScroll();
No uso jquery y no quiero; ¿Existe todavía una manera inteligente pero simple de hacer o extender $anchorScroll
para hacer el desplazamiento más suave?
Alan, gracias. Si alguien está interesado, lo formateé según los estándares de 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);
}
}
}
};
};
})();
Desafortunadamente esto no es posible usando $anchorScroll
. Como descubriste, $anchorScroll
no tiene ninguna opción y no funciona con $ngAnimate
. Para animar el rollo, necesitaría usar su propio servicio / fábrica o simplemente javascript directo.
Por el bien del autoaprendizaje, armé un ejemplo con un servicio de desplazamiento suave. Probablemente haya mejores formas de hacerlo así que se recomienda cualquier comentario.
Para desplazarse a un elemento, adjunte un ng-click="gotoElement(ID)"
a cualquier elemento. Creo que una ruta aún mejor sería hacer de esto una directiva.
Aquí está el ejemplo de trabajo en jsFiddle .
Actualizar
Ahora hay una serie de directivas de terceros para lograr esto.
La respuesta de Brett funcionó muy bien para mí. Hice algunos pequeños cambios en su solución en términos de modularización y capacidad de prueba.
Aquí hay otro ejemplo de trabajo en JsFiddle que incluye la otra versión con pruebas incluidas.
Para las pruebas, estoy usando Karma y Jasmine. La firma ha sido ligeramente modificada de la siguiente manera:
anchorSmoothScroll.scrollTo(elementId, speed);
Donde el elemento es un atributo obligatorio para desplazarse y la velocidad es opcional cuando el valor predeterminado es 20 (como era antes).
Ninguna de las soluciones aquí realmente hace lo que OP pidió originalmente, es decir, hace que $anchorScroll
desplace suavemente. La diferencia entre las directivas de desplazamiento suave y $anchroScroll
es que usa / modifica $location.hash()
, lo que puede ser deseable en algunos casos.
Aquí está la esencia del módulo simple que reemplaza $ anchorScroll scrolling con desplazamiento suave. Utiliza la biblioteca https://github.com/oblador/angular-scroll para desplazarse por sí misma (reemplázala por otra cosa si quieres, debería ser fácil).
https://gist.github.com/mdvorak/fc8b531d3e082f3fdaa9
Nota: En realidad, no obtiene $ anchorScroll para desplazarse sin problemas, pero reemplaza su controlador para desplazarse.
Habilítelo simplemente haciendo referencia mdvorakSmoothScroll
módulo mdvorakSmoothScroll
en su aplicación.
No estoy al tanto de cómo animar $anchorScroll
. Así es como lo hago en mis proyectos:
/* Scroll to top on each ui-router state change */
$rootScope.$on(''$stateChangeStart'', function() {
scrollToTop();
});
Y la función 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;
}
También puede usar el desplazamiento angular, enlace " https://github.com/durated/angular-scroll/ ". Es un desplazamiento suave y algunas funciones de relajación para obtener un aspecto profesional.
También puede usar ngSmoothScroll, enlace: https://github.com/d-oliveros/ngSmoothScroll .
Simplemente incluya el módulo smoothScroll
como una dependencia y utilícelo de esta manera:
<a href="#" scroll-to="my-element-3">Click me!</a>