Можно ли анимировать scrollTop с помощью jQuery?

226

Я хочу плавно прокрутить вниз. Я не хочу писать для этого функцию, особенно если она есть в jQuery.

Брайан Филд
источник

Ответы:

463

Вы можете просто использовать .animate()в scrollTopсобственность, как это:

$("html, body").animate({ scrollTop: "300px" });
Ник Крейвер
источник
Очень хорошо .. нет необходимости использовать плагины для этого.
Amol M Kulkarni
15
Зачем тебе и то htmlи другое body? Здесь есть некоторая идея: stackoverflow.com/questions/2123690/… , но это не полный ответ.
Харалан Добрев
28
body используется webkit, html используется firefox.
Джори
2
FYI: Если <html>есть overflow-x:hidden;это одушевленные не будет работать. (Может не работать overflow-y:hidden, и overflow:hidden, но я не проверял.
collinhaines
1
Я думаю, что bodyработал в Chrome в начале этого года, но теперь это должно быть html.
Ник Дэвис,
73

Ответ Ника прекрасно работает. Будьте осторожны при указании функции complete () внутри вызова animate (), поскольку он будет выполнен дважды, поскольку у вас объявлены два селектора (html и body).

$("html, body").animate(
    { scrollTop: "300px" },
    {
        complete : function(){
            alert('this alert will popup twice');
        }
    }
);

Вот как вы можете избежать двойного обратного вызова.

var completeCalled = false;
$("html, body").animate(
    { scrollTop: "300px" },
    {
        complete : function(){
            if(!completeCalled){
                completeCalled = true;
                alert('this alert will popup once');
            }
        }
    }
);
Kita
источник
1
Вопрос в том, зачем вам анимировать «html, body», а не просто «body»?
Лиор
21
Потому что в зависимости от того, какой у вас браузер, вы можете либо анимировать тело, либо HTML. Анимируя ОБА, вы покрываете больше браузеров.
Bene
Но в этом случае он действительно появится только один раз, даже если его нужно вызывать повторно (событие нажатия кнопки) или я что-то пропустил?
HoGo
Да, в этом случае он появится только один раз. Если вам необходимо повторно анимировать, вы должны сделать переменную completeCalled локальной для функции обратного вызова, которая выполняет функцию animate. Таким образом, он будет всплывать только один раз при нажатии, но он будет всплывать снова (только один раз) при повторном нажатии.
Кита
Чтобы предотвратить срабатывание функции двойного обратного вызова, вы можете использовать die()функцию перед live()вызовом функции. Это гарантирует, что ваш live()обработчик будет вызван только один раз.
Лорд Найтон
27

Ответ Ника отлично работает, а настройки по умолчанию хороши, но вы можете более полно контролировать прокрутку, выполнив все дополнительные настройки.

вот как это выглядит в API:

.animate( properties [, duration] [, easing] [, complete] )

так что вы можете сделать что-то вроде этого:

.animate( 
    {scrollTop:'300px'},
    300,
    swing,
    function(){ 
       alert(animation complete! - your custom code here!); 
       } 
    )

Вот страница API функции jQuery .animate: http://api.jquery.com/animate/

следопыт
источник
15

Как упоминал Кит, существует проблема с несколькими обратными вызовами, запускаемыми, когда вы анимируете как 'html', так и 'body'. Вместо того, чтобы анимировать и блокировать последующие обратные вызовы, я предпочитаю использовать некоторые базовые функции обнаружения и анимировать только свойство scrollTop одного объекта.

Принятый ответ в этом другом потоке дает некоторое представление о том, какое свойство scrollTop объекта мы должны попытаться анимировать: прокрутка и анимация pageYOffset в 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...
    })
});

ОБНОВИТЬ - - -

Вышеуказанная попытка обнаружения функции не удалась. Похоже, что не существует однострочного способа сделать это, так как свойство pageYOffset в браузерах с типом webkit всегда возвращает ноль при наличии типа документа. Вместо этого я нашел способ использовать обещание для выполнения одного обратного вызова при каждом выполнении анимации.

$('html, body')
    .animate({ scrollTop: 100 })
    .promise()
    .then(function(){
        // callback code here
    })
});
Стивен
источник
1
Использование обещания () здесь гениально.
Аллан Базинет
Это требует больше голосов. Я никогда не видел, чтобы обещание использовалось для этого раньше, и это то, что я заканчиваю поиском каждые несколько месяцев. Как сказал Аллан, гений.
Тортиламан
14

У меня есть то, что я считаю, лучшее решение, чем $('html, body')взломать.

Это не одна строка, но проблема, с которой я столкнулся, $('html, body')заключается в том,$(window).scrollTop() в во время анимации, вы увидите, что значение скачет повсюду, иногда на сотни пикселей (хотя я не вижу ничего подобного происходит визуально). Мне нужно было, чтобы значение было предсказуемым, чтобы я мог отменить анимацию, если пользователь нажал полосу прокрутки или повернул колесо мыши во время автопрокрутки.

Вот эта функция будет плавно анимировать прокрутку:

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

Ниже приведена более сложная версия, которая будет отменять анимацию при взаимодействии с пользователем, а также переопределение до достижения целевого значения, что полезно при попытке мгновенно установить scrollTop (например, при простом вызове $(window).scrollTop(1000)- по моему опыту это не помогает 50% времени.)

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);
                    }
                }
            }
        );
    }
}
Джон Старр Дьюар
источник
7

У меня были проблемы, когда анимация всегда начиналась сверху страницы после обновления страницы в других примерах.

Я исправил это, не анимируя CSS напрямую, а вызывая window.scrollTo();каждый шаг:

$({myScrollTop:window.pageYOffset}).animate({myScrollTop:300}, {
  duration: 600,
  easing: 'swing',
  step: function(val) {
    window.scrollTo(0, val);
  }
});

Это также получает вокруг htmlпротив bodyвопроса , как он использует кросс-браузер JavaScript.

Загляните на http://james.padolsey.com/javascript/fun-with-jquerys-animate/ для получения дополнительной информации о том, что вы можете сделать с помощью функции анимирования jQuery.

complistic
источник
5

Вы можете использовать анимацию jQuery для прокрутки страницы с определенной продолжительностью:

$("html, body").animate({scrollTop: "1024px"}, 5000);

где 1024px - смещение прокрутки, а 5000 - продолжительность анимации в миллисекундах.

Алессандро Пировано
источник
Отличный ответ! Рад, что вы включили вариант продолжительности. Просто хотел добавить, что $("html, body").animate({scrollTop: 1024}, 5000);тоже работает.
Райан Тейлор
4

Попробуйте плагин scrollTo .

Тату Ульманен
источник
Похоже, что scrollTo больше не является проектом на этом сайте.
Джим
Код для этого очень прост. Зачем вам добавлять плагин, чтобы делать то, что вы можете сделать с одной строкой кода?
Гэвин
4
Четыре года назад это было не так просто .. :)
Тату Ульманен,
4
$(".scroll-top").on("click", function(e){
   e.preventDefault();
   $("html, body").animate({scrollTop:"0"},600);
});
Рубель Хоссейн
источник
1

Если вы хотите перейти вниз в конце страницы (поэтому вам не нужно прокручивать страницу вниз), вы можете использовать:

$('body').animate({ scrollTop: $(document).height() });
Маленький муравей
источник
0

Но если вы действительно хотите добавить анимацию во время прокрутки, вы можете попробовать мой простой плагин ( AnimateScroll ), который в настоящее время поддерживает более 30 стилей смягчения.

Рам Патра
источник
-3

кросс-браузерный код:

$(window).scrollTop(300); 

это без анимации, но работает везде

user2760861
источник
6
Я искал способ "оживить scrollTop с помощью jQuery?" Ответ «без анимации» не является ответом.
Брайан Филд