Чи можливо анімувати 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

Відповідь Ніка працює чудово. Будьте обережні, вказуючи функцію завершення () всередині виклику 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');
            }
        }
    }
);

1
Питання в тому, чому б ви оживляли "html, body", а не просто "body"?
Ліор

21
Тому що залежно від того, який ви переглядач, ви можете або анімувати тіло АБО html. Анімацією BOTH ви охоплюєте більше браузерів.
Бене

Але в цьому випадку воно з’явиться дійсно лише один раз, також якщо його потрібно буде викликати повторно (натиснути подію на кнопку) або я щось пропустив?
HoGo

Так, у цьому випадку він з’явиться лише один раз. Якщо вам потрібно буде анімувати кілька разів, ви зробите змінну completeCalled локальною для функції зворотного виклику, яка виконує функцію анімації. Таким чином, він все ще з’явиться лише один раз, коли ви клацнете, але він з’явиться знову (лише один раз), коли ви знову натиснете.
Кіта

Для запобігання запуску функції подвійного виклику ви можете використовувати 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 Scrolling and Animation в 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...
    })
});

ОНОВЛЕННЯ - - -

Наведена вище спроба виявлення функцій не вдалася. Схоже, немає однолінійного способу зробити це як сторінка веб-переглядачів webkitYOYOU властивість завжди повертає нуль, коли існує доктіп. Натомість я знайшов спосіб використовувати обіцянку робити єдиний зворотний дзвінок щоразу, коли анімація виконується.

$('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);
  }
});

Це також вирішує проблему htmlvs, bodyоскільки вона використовує крос-браузер JavaScript.

Перегляньте сторінку http://james.padolsey.com/javascript/fun-with-jquerys-animate/, щоб отримати докладнішу інформацію про те, що можна зробити з функцією анімації jQuery.


5

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

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

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


Чудова відповідь! Радий, що ви включили варіант тривалості. Просто хотів додати, що $("html, body").animate({scrollTop: 1024}, 5000);також працює.
Райан Тейлор

4

Спробуйте прокручувати плагін.


Здається, що scrollTo більше не є проектом на цьому сайті.
Джим

Код для цього дуже простий. Чому б ви додали плагін, щоб зробити щось, що ви можете зробити з одним рядком коду?
Гевін

4
Чотири роки тому це було не так просто .. :)
Тату Ульманен


1

Якщо ви хочете рухатися вниз в кінці сторінки (тому вам не потрібно прокручувати вниз), ви можете скористатися:

$('body').animate({ scrollTop: $(document).height() });

0

Але якщо ви дійсно хочете додати деяку анімацію під час прокрутки, ви можете спробувати мій простий плагін ( AnimateScroll ), який наразі підтримує більше 30 стилів полегшення


-3

перехресний код браузера:

$(window).scrollTop(300); 

це без анімації, але працює скрізь


6
Я шукав спосіб "анімувати scrollTop за допомогою jQuery?" Відповідь "без анімації" - це не відповідь.
Брайан Поле
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.