เป็นไปได้ที่จะเคลื่อนไหว scrollTop กับ jQuery หรือไม่?


226

ฉันต้องการเลื่อนลงอย่างราบรื่น ฉันไม่ต้องการที่จะเขียนฟังก์ชั่นสำหรับสิ่งนั้น - โดยเฉพาะถ้า jQuery มีอยู่แล้ว

คำตอบ:


463

คุณก็สามารถใช้คุณสมบัติเช่นนี้.animate()scrollTop

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

เยี่ยมมาก .. ไม่จำเป็นต้องใช้ปลั๊กอินสำหรับสิ่งนี้
Amol M Kulkarni

15
ทำไมคุณต้องทั้งสองhtmlและbody? มีข้อมูลเชิงลึกบางอย่างที่นี่: stackoverflow.com/questions/2123690/…แต่มันไม่ใช่คำตอบที่สมบูรณ์
Haralan Dobrev

28
body ถูกใช้โดย webkit, html ถูกใช้โดย firefox
Jory

2
FYI: หาก<html>มีoverflow-x:hidden;การเคลื่อนไหวนี้จะไม่ทำงาน (อาจไม่ทำงานoverflow-y:hiddenและoverflow:hiddenแต่ฉันยังไม่ได้ทดสอบ
collinhaines

1
ฉันคิดว่าใช้bodyงานได้ใน Chrome เมื่อต้นปีนี้ แต่ตอนนี้มันต้องเป็นhtmlแล้ว
Nick Davies

73

คำตอบของนิคนั้นใช้งานได้ดี ระวังเมื่อระบุฟังก์ชั่นสมบูรณ์ () ภายในการโทรเคลื่อนไหว () เพราะจะได้รับการดำเนินการสองครั้งเนื่องจากคุณได้ประกาศตัวเลือกสองตัว (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'
Lior

21
เพราะขึ้นอยู่กับว่าคุณเป็นเบราว์เซอร์ใดคุณจึงสามารถเคลื่อนไหวร่างกายหรือ html ได้ โดยการเคลื่อนไหวทั้งสองนี้คุณจะครอบคลุมเบราว์เซอร์มากขึ้น
Bene

แต่ในกรณีนี้มันจะป็อปอัพเพียงครั้งเดียวจริงๆถ้ามันต้องถูกเรียกซ้ำ ๆ (คลิกที่ปุ่มเหตุการณ์) หรือฉันพลาดอะไรบางอย่าง?
HoGo

ใช่ในกรณีนี้จะป๊อปอัปเพียงครั้งเดียว หากคุณต้องการเคลื่อนไหวซ้ำ ๆ คุณจะทำให้ตัวแปร completeCalled ภายในเครื่องไปยังฟังก์ชันการเรียกกลับที่ดำเนินการฟังก์ชันการเคลื่อนไหว ด้วยวิธีนี้มันจะยังคงป็อปอัพเพียงครั้งเดียวเมื่อคุณคลิก แต่มันจะป๊อปอัพอีกครั้ง (เพียงครั้งเดียว) เมื่อคุณคลิกอีกครั้ง
Kita

เพื่อป้องกันไม่ให้ฟังก์ชันเรียกกลับสองครั้งคุณสามารถใช้die()ฟังก์ชันก่อนlive()เรียกใช้ฟังก์ชัน การรับประกันนี้live()ผู้บริหารของคุณจะถูกเรียกเพียงครั้งเดียว
Lord Nighton

27

คำตอบของ Nick ทำงานได้ดีและการตั้งค่าเริ่มต้นนั้นดี แต่คุณสามารถควบคุมการเลื่อนได้อย่างสมบูรณ์ยิ่งขึ้นโดยการตั้งค่าเพิ่มเติมทั้งหมด

นี่คือลักษณะที่ปรากฏใน 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

เช่นเดียวกับ Kita ที่กล่าวถึงมีปัญหากับการโทรกลับหลายครั้งเมื่อคุณเคลื่อนไหวทั้ง '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...
    })
});

อัพเดท - - -

ความพยายามในการตรวจหาคุณสมบัติข้างต้นล้มเหลว ดูเหมือนว่าไม่มีวิธีใดวิธีหนึ่งในการทำเช่นนี้เนื่องจากคุณสมบัติของเบราว์เซอร์ชนิด webkit pageYOffset จะส่งคืนค่าศูนย์เมื่อมีประเภทของประเภทเสมอ ฉันพบวิธีใช้สัญญาในการโทรกลับครั้งเดียวทุกครั้งที่มีการเคลื่อนไหว

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

1
ใช้สัญญา () นี่คืออัจฉริยะ
Allan Bazinet

สิ่งนี้ต้องการ upvotes มากขึ้น ฉันไม่เคยเห็นสัญญาใช้มาก่อนและนี่คือสิ่งที่ฉันท้ายค้นหาทุกสองสามเดือน อย่างอัลลันกล่าวว่าอัจฉริยะ
Tortilaman

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

ด้านล่างเป็นรุ่นที่ซับซ้อนมากขึ้นที่จะยกเลิกการเคลื่อนไหวในการโต้ตอบกับผู้ใช้รวมถึงการ refiring จนกว่าจะถึงค่าเป้าหมายซึ่งมีประโยชน์เมื่อพยายามตั้ง 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);
  }
});

นอกจากนี้ยังได้รับรอบhtmlvsbodyแก้ไขปัญหาเมื่อใช้จาวาสคริปต์ข้ามเบราว์เซอร์

ดูhttp://james.padolsey.com/javascript/fun-with-jquerys-animate/สำหรับข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่คุณสามารถทำได้ด้วยฟังก์ชั่นภาพเคลื่อนไหวของ jQuery


5

คุณสามารถใช้ภาพเคลื่อนไหว jQuery สำหรับหน้าเลื่อนที่มีระยะเวลาเฉพาะ:

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

โดยที่ 1024px คือ offset offset และ 5,000 คือระยะเวลาของการเคลื่อนไหวเป็นมิลลิวินาที


คำตอบที่ดี! ดีใจที่คุณรวมตัวเลือกระยะเวลา เพียงแค่ต้องการที่จะเพิ่มที่$("html, body").animate({scrollTop: 1024}, 5000);ยังใช้งานได้
Ryan Taylor

4

ลองใช้ ปลั๊กอินscrollTo


ดูเหมือนว่า scrollTo จะไม่เป็นโครงการในไซต์นั้นอีกต่อไป
Jim

รหัสเพื่อให้บรรลุนี้ง่ายมาก เหตุใดคุณจึงต้องเพิ่มปลั๊กอินเพื่อทำสิ่งที่คุณสามารถทำได้ด้วยโค้ดหนึ่งบรรทัด
Gavin

4
สี่ปีที่ผ่านมามันก็ไม่ได้ง่ายดังนั้น .. :)
Tatu Ulmanen


1

หากคุณต้องการเลื่อนลงที่ส่วนท้ายของหน้า (ดังนั้นคุณไม่จำเป็นต้องเลื่อนลงไปด้านล่าง) คุณสามารถใช้:

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

0

แต่ถ้าคุณต้องการที่จะเพิ่มภาพเคลื่อนไหวบางอย่างในขณะที่เลื่อนคุณสามารถลองปลั๊กอินอย่างง่ายของฉัน ( AnimateScroll ) ซึ่งปัจจุบันสนับสนุนมากกว่า 30 รูปแบบการผ่อนคลาย


-3

รหัสเบราว์เซอร์ข้ามคือ:

$(window).scrollTop(300); 

มันไม่มีภาพเคลื่อนไหว แต่ใช้ได้ทุกที่


6
ฉันกำลังมองหาวิธี "การเคลื่อนไหว scrollTop กับ jQuery?" คำตอบที่เป็น "ไม่มีภาพเคลื่อนไหว" ไม่ใช่คำตอบ
ไบรอันฟิลด์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.