Je veux pouvoir faire défiler les pages en douceur. Je ne veux pas avoir à écrire une fonction pour cela - surtout si jQuery en a déjà une.
Réponses
Trop de publicités?Vous pouvez simplement utiliser .animate()
le site scrollTop
comme ceci :
$("html, body").animate({ scrollTop: "300px" });
La réponse de Nick fonctionne très bien. Faites attention lorsque vous spécifiez une fonction complete() à l'intérieur de l'appel animate() car elle sera exécutée deux fois puisque vous avez déclaré deux sélecteurs (html et body).
$("html, body").animate(
{ scrollTop: "300px" },
{
complete : function(){
alert('this alert will popup twice');
}
}
);
Voici comment vous pouvez éviter le double rappel.
var completeCalled = false;
$("html, body").animate(
{ scrollTop: "300px" },
{
complete : function(){
if(!completeCalled){
completeCalled = true;
alert('this alert will popup once');
}
}
}
);
La réponse de Nick fonctionne très bien et les paramètres par défaut sont agréables, mais vous pouvez mieux contrôler le défilement en complétant tous les paramètres optionnels.
Voici à quoi cela ressemble dans l'API :
.animate( properties [, duration] [, easing] [, complete] )
donc vous pourriez faire quelque chose comme ça :
.animate(
{scrollTop:'300px'},
300,
swing,
function(){
alert(animation complete! - your custom code here!);
}
)
voici la page d'api de la fonction jQuery .animate : http://api.jquery.com/animate/
Comme Kita l'a mentionné, il y a un problème avec le déclenchement de plusieurs callbacks lorsque vous animez à la fois "html" et "body". Au lieu d'animer les deux et de bloquer les rappels suivants, je préfère utiliser une détection de base des caractéristiques et n'animer que la propriété scrollTop d'un seul objet.
La réponse acceptée sur cet autre fil de discussion donne un aperçu de la propriété scrollTop de l'objet que nous devons essayer d'animer : Défilement et animation de la pageYOffset dans IE8
// UPDATE: don't use this... see below
// only use 'body' for IE8 and below
var scrollTopElement = (window.pageYOffset != null) ? 'html' : 'body';
// only animate on one element so our callback only fires once!
$(scrollTopElement).animate({
scrollTop: '400px' // vertical position on the page
},
500, // the duration of the animation
function() {
// callback goes here...
})
});
MISE À JOUR - - -
La tentative ci-dessus de détection des caractéristiques échoue. Il semble qu'il n'y ait pas de moyen unique de le faire, car la propriété pageYOffset des navigateurs de type webkit renvoie toujours zéro lorsqu'il y a un doctype. Au lieu de cela, j'ai trouvé un moyen d'utiliser une promesse pour faire un seul callback pour chaque fois que l'animation s'exécute.
$('html, body')
.animate({ scrollTop: 100 })
.promise()
.then(function(){
// callback code here
})
});
J'ai ce que je crois être une meilleure solution que la $('html, body')
pirate.
Ce n'est pas une phrase toute faite, mais le problème que j'avais avec $('html, body')
est que si vous vous connectez $(window).scrollTop()
Pendant l'animation, vous verrez que la valeur saute partout, parfois de plusieurs centaines de pixels (bien que je ne voie rien de tel visuellement). J'avais besoin que la valeur soit prévisible, afin de pouvoir annuler l'animation si l'utilisateur saisit la barre de défilement ou fait tourner la molette de la souris pendant le défilement automatique.
Voici une fonction qui animera le défilement en douceur :
function animateScrollTop(target, duration) {
duration = duration || 16;
var scrollTopProxy = { value: $(window).scrollTop() };
if (scrollTopProxy.value != target) {
$(scrollTopProxy).animate(
{ value: target },
{ duration: duration, step: function (stepValue) {
var rounded = Math.round(stepValue);
$(window).scrollTop(rounded);
}
});
}
}
Vous trouverez ci-dessous une version plus complexe qui annulera l'animation en cas d'interaction avec l'utilisateur, et qui la réactivera jusqu'à ce que la valeur cible soit atteinte, ce qui est utile lorsque vous essayez de définir le scrollTop instantanément (par exemple, en appelant tout simplement $(window).scrollTop(1000)
- d'après mon expérience, cela ne fonctionne pas dans environ 50 % des cas).
function animateScrollTop(target, duration) {
duration = duration || 16;
var $window = $(window);
var scrollTopProxy = { value: $window.scrollTop() };
var expectedScrollTop = scrollTopProxy.value;
if (scrollTopProxy.value != target) {
$(scrollTopProxy).animate(
{ value: target },
{
duration: duration,
step: function (stepValue) {
var roundedValue = Math.round(stepValue);
if ($window.scrollTop() !== expectedScrollTop) {
// The user has tried to scroll the page
$(scrollTopProxy).stop();
}
$window.scrollTop(roundedValue);
expectedScrollTop = roundedValue;
},
complete: function () {
if ($window.scrollTop() != target) {
setTimeout(function () {
animateScrollTop(target);
}, 16);
}
}
}
);
}
}