Có thể tạo hiệu ứng scrollTop với jQuery không?


226

Tôi muốn di chuyển trơn tru xuống. Tôi không muốn phải viết một hàm cho điều đó - đặc biệt là nếu jQuery đã có.

Câu trả lời:


463

Bạn chỉ có thể sử dụng .animate()các scrollToptài sản, như thế này:

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

Rất đẹp .. không cần sử dụng plugin cho việc này.
Amol M Kulkarni

15
Tại sao bạn cần cả hai htmlbody? Có một số cái nhìn sâu sắc ở đây: stackoverflow.com/questions/2123690/ , nhưng nó không phải là một câu trả lời hoàn chỉnh.
Haralan Dobrev

28
cơ thể được sử dụng bởi webkit, html được sử dụng bởi firefox.
Jory

2
FYI: Nếu <html>overflow-x:hidden;hoạt hình này sẽ không hoạt động. (Có thể không hoạt động overflow-y:hidden, và overflow:hidden, nhưng tôi chưa thử nghiệm.
collinhaines

1
Tôi nghĩ rằng bodyđã làm việc trong Chrome vào đầu năm nay, nhưng bây giờ nó phải như vậy html.
Nick Davies

73

Câu trả lời của Nick hoạt động rất tốt. Hãy cẩn thận khi chỉ định một hàm () hoàn chỉnh bên trong lệnh gọi animate () bởi vì nó sẽ được thực thi hai lần vì bạn có hai bộ chọn được khai báo (html và thân).

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

Đây là cách bạn có thể tránh cuộc gọi lại kép.

var completeCalled = false;
$("html, body").animate(
    { scrollTop: "300px" },
    {
        complete : function(){
            if(!completeCalled){
                completeCalled = true;
                alert('this alert will popup once');
            }
        }
    }
);

1
Câu hỏi là, tại sao bạn lại làm động 'html, cơ thể' chứ không chỉ là 'cơ thể'?
Lior

21
Bởi vì tùy thuộc vào trình duyệt của bạn, bạn có thể làm động cơ thể HOẶC html. Bằng cách tạo hiệu ứng CẢ HAI, bạn bao quát nhiều trình duyệt hơn.
Bene

Nhưng trong trường hợp này, nó sẽ bật lên thực sự chỉ một lần, ngoài ra nếu nó phải được gọi liên tục (nhấp vào sự kiện trên nút) hoặc tôi đã bỏ lỡ điều gì?
HoGo

Vâng, trong trường hợp này, nó sẽ chỉ bật lên một lần. Nếu bạn cần phải tạo hiệu ứng lặp đi lặp lại, bạn sẽ biến biến hoàn chỉnh thành cục bộ thành hàm gọi lại thực thi hàm animate. Bằng cách đó, nó sẽ vẫn chỉ bật lên một lần khi bạn nhấp, nhưng nó sẽ bật lại (chỉ một lần) khi bạn nhấp lại.
Kita

Để ngăn chức năng gọi lại đôi, bạn có thể sử dụng die()chức năng trước khi live()gọi chức năng. Điều này đảm bảo, rằng live()trình xử lý của bạn sẽ chỉ được gọi một lần.
Lord Nighton

27

Câu trả lời của Nick hoạt động rất tốt và các cài đặt mặc định rất hay, nhưng bạn có thể kiểm soát cuộn hoàn toàn hơn bằng cách hoàn thành tất cả các cài đặt tùy chọn.

Đây là những gì nó trông giống như trong API:

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

vì vậy bạn có thể làm một cái gì đó như thế này:

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

đây là trang api hàm jQuery .animate: http://api.jquery.com/animate/


15

Giống như Kita đã đề cập, có một vấn đề với nhiều cuộc gọi lại bắn khi bạn hoạt hình trên cả 'html' và 'body'. Thay vì hoạt hình cả hai và chặn các cuộc gọi lại tiếp theo, tôi thích sử dụng một số tính năng phát hiện tính năng cơ bản và chỉ làm động các thuộc tính scrollTop của một đối tượng.

Câu trả lời được chấp nhận cho chủ đề khác này cung cấp một số thông tin chi tiết về thuộc tính scrollTop của đối tượng mà chúng ta nên cố gắng tạo hiệu ứng: pageYPackset Scrolling và Animation trong 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...
    })
});

CẬP NHẬT - - -

Nỗ lực phát hiện tính năng trên không thành công. Có vẻ như không có cách nào để thực hiện điều đó vì các trình duyệt loại webkit, thuộc tínhYPackset luôn trả về 0 khi có một loại tài liệu. Thay vào đó, tôi tìm thấy một cách để sử dụng một lời hứa để thực hiện một cuộc gọi lại cho mỗi lần hoạt hình thực thi.

$('html, body')
    .animate({ scrollTop: 100 })
    .promise()
    .then(function(){
        // callback code here
    })
});

1
Sử dụng lời hứa () ở đây là thiên tài.
Allan Bazinet

Điều này cần nhiều upvote. Tôi chưa bao giờ thấy lời hứa được sử dụng cho điều này trước đây và đây là điều tôi cuối cùng tìm kiếm trong vài tháng. Như Allan đã nói, thiên tài.
Tortilaman

14

Tôi có những gì tôi tin là một giải pháp tốt hơn so với $('html, body')hack.

Đó không phải là một lớp lót, nhưng vấn đề tôi gặp phải $('html, body')là nếu bạn đăng nhập $(window).scrollTop()trong khi hoạt hình, bạn sẽ thấy giá trị đó nhảy khắp nơi, đôi khi là hàng trăm pixel (mặc dù tôi không thấy gì như vậy xảy ra trực quan). Tôi cần giá trị để có thể dự đoán được, để tôi có thể hủy hoạt hình nếu người dùng nắm lấy thanh cuộn hoặc xoay tròn con lăn trong quá trình tự động cuộn.

Đây là một chức năng sẽ hoạt hình cuộn trơn tru:

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

Dưới đây là phiên bản phức tạp hơn sẽ hủy hoạt hình khi tương tác với người dùng, cũng như nạp lại cho đến khi đạt được giá trị đích, rất hữu ích khi cố gắng đặt scrollTop ngay lập tức (ví dụ như gọi $(window).scrollTop(1000)- theo kinh nghiệm của tôi, điều này không hoạt động 50% thời gian.)

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

Tôi đã gặp vấn đề trong đó hoạt hình luôn bắt đầu từ đầu trang sau khi làm mới trang trong các ví dụ khác.

Tôi đã sửa lỗi này bằng cách không tạo hiệu ứng trực tiếp cho css mà chỉ gọi window.scrollTo();từng bước:

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

Điều này cũng xoay quanh vấn đề htmlso với bodykhi sử dụng JavaScript trên nhiều trình duyệt.

Hãy xem http://james.padolsey.com/javascript/fun-with-jquerys-animate/ để biết thêm thông tin về những gì bạn có thể làm với chức năng hoạt hình của jQuery.


5

Bạn có thể sử dụng hoạt hình jQuery cho trang cuộn với thời lượng cụ thể:

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

trong đó 1024px là phần bù cuộn và 5000 là thời lượng của hình ảnh động tính bằng mili giây.


Câu trả lời chính xác! Vui mừng bạn bao gồm các tùy chọn thời lượng. Chỉ muốn thêm mà $("html, body").animate({scrollTop: 1024}, 5000);cũng hoạt động.
Ryan Taylor

4

Hãy thử plugin scrollTo .


Dường như scrollTo không còn là một dự án tại trang web đó.
Jim

Mã để thực hiện điều này là rất đơn giản. Tại sao bạn lại thêm một plugin để làm điều gì đó bạn có thể làm với một dòng mã?
Gavin

4
Bốn năm trước mọi chuyện không đơn giản như vậy .. :)
Tatu Ulmanen

4
$(".scroll-top").on("click", function(e){
   e.preventDefault();
   $("html, body").animate({scrollTop:"0"},600);
});

1

Nếu bạn muốn di chuyển xuống cuối trang (vì vậy bạn không cần phải cuộn xuống dưới cùng), bạn có thể sử dụng:

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

0

Nhưng nếu bạn thực sự muốn thêm một số hình ảnh động trong khi cuộn, bạn có thể thử plugin đơn giản của tôi ( AnimateScroll ) hiện hỗ trợ hơn 30 kiểu nới lỏng


-3

mã trình duyệt chéo là:

$(window).scrollTop(300); 

Nó không có hoạt hình nhưng hoạt động ở mọi nơi


6
Tôi đang tìm cách "để tạo hiệu ứng scrollTop với jQuery?" Một câu trả lời là "không có hoạt hình" không phải là một câu trả lời.
Bryan Field
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.