ฉันจะเลื่อนไปที่องค์ประกอบภายใน Div ที่โอเวอร์โฟลว์ได้อย่างไร


159

ฉันมี 20 รายการใน div ที่สามารถแสดงได้ 5 รายการต่อครั้ง วิธีที่ดีในการเลื่อนไปยังรายการ # 10 คืออะไรแล้วรายการ # 20 ฉันรู้ความสูงของทุกรายการ

scrollToปลั๊กอินทำอย่างนี้ แต่แหล่งที่มาของมันไม่ได้ง่ายสุดที่จะเข้าใจได้โดยไม่ต้องได้รับจริงๆเป็นมัน ฉันไม่ต้องการใช้ปลั๊กอินนี้

สมมติว่าผมมีฟังก์ชั่นที่ใช้เวลา 2 องค์ประกอบ$parentDiv, $innerListItem, ค่า$innerListItem.offset().topมิได้$innerListItem.positon().topให้ฉัน scrollTop ที่ถูกต้องสำหรับ $ parentDiv


ลบคำตอบของฉันเนื่องจากการปรับปรุงของคุณ แต่เชื่อฉันเถอะว่าก่อนหน้านี้มีทัศนคติแบบเดียวกันมีเบราว์เซอร์จำนวนมากที่มีตำแหน่งและระยะขอบ ฯลฯ ... ปลั๊กอินเป็นเส้นทางที่ง่ายกว่ามากและใช้เวลาน้อยลงและมีเพียง 3k ก่อน GZip
Nick Craver

1
ใช้ปลั๊กอิน scrollTo ต่อไป มันไม่ยาก $("#container").scrollTo(target, duration, options). #anchorเป้าหมายเป็นเพียง เสร็จสิ้น
Ryan McGeary

ดูเหมือนว่าควรมีความรู้ในการทำเช่นนี้โดยไม่มีปลั๊กอิน พรุ่งนี้ป่วยเริ่มอ่านซอร์ส
mkoryak

5
@mkoryak - มีความรู้อยู่ที่นั่น แต่เมื่อคุณอธิบายถึงนิสัยใจคอของเบราว์เซอร์คุณจะต้องจบลงด้วย ... ปลั๊กอิน. scrollToดังนั้นทำไมต้องคิดค้นวงล้อใหม่อยู่ตลอดเวลา?
Nick Craver

1
IMHO คุณอาจจะจบลงด้วยเซตที่แน่นอนของสิ่งที่คุณต้องการจาก .scrollTo วันนี้ แต่ในเวลาไม่กี่เดือนในขณะที่. scrollTo ได้รับการอัปเดตเป็น IE9, FF4 และ Chrome 6 คุณจะต้องเริ่มต้นใหม่ ... 3k ดูเหมือนว่าราคาต่ำมากเพื่อหลีกเลี่ยงปัญหานี้
Wim

คำตอบ:


236

$innerListItem.position().topเป็นจริงเมื่อเทียบกับ.scrollTop()ของบรรพบุรุษตำแหน่งเป็นครั้งแรก ดังนั้นวิธีการคำนวณ$parentDiv.scrollTop()ค่าที่ถูกต้องคือการเริ่มต้นด้วยการทำให้แน่ใจว่า$parentDivมีการวางตำแหน่ง ถ้ามันไม่ได้อยู่แล้วมีความชัดเจนการใช้งานposition position: relativeองค์ประกอบ$innerListItemและบรรพบุรุษทั้งหมด$parentDivจำเป็นต้องไม่มีตำแหน่งที่ชัดเจน ตอนนี้คุณสามารถเลื่อนไปที่$innerListItemด้วย:

// Scroll to the top
$parentDiv.scrollTop($parentDiv.scrollTop() + $innerListItem.position().top);

// Scroll to the center
$parentDiv.scrollTop($parentDiv.scrollTop() + $innerListItem.position().top
    - $parentDiv.height()/2 + $innerListItem.height()/2);

152

นี่คือปลั๊กอินของฉันเอง (จะวางตำแหน่งองค์ประกอบไว้ด้านบนของรายการพิเศษสำหรับoverflow-y : autoอาจไม่ทำงานด้วยoverflow-x!):

หมายเหตุ : elemเป็นตัวเลือก HTML ขององค์ประกอบที่หน้าจะถูกเลื่อนไป สิ่งที่ได้รับการสนับสนุนโดย jQuery เช่น: #myid, div.myclass, $(jquery object)[วัตถุ Dom] ฯลฯ

jQuery.fn.scrollTo = function(elem, speed) { 
    $(this).animate({
        scrollTop:  $(this).scrollTop() - $(this).offset().top + $(elem).offset().top 
    }, speed == undefined ? 1000 : speed); 
    return this; 
};

หากคุณไม่ต้องการให้ภาพเคลื่อนไหวใช้:

jQuery.fn.scrollTo = function(elem) { 
    $(this).scrollTop($(this).scrollTop() - $(this).offset().top + $(elem).offset().top); 
    return this; 
};

วิธีใช้:

$("#overflow_div").scrollTo("#innerItem");
$("#overflow_div").scrollTo("#innerItem", 2000); //custom animation speed 

หมายเหตุ: สามารถเป็นที่ใดก็ได้ภายใน#innerItem #overflow_divไม่จำเป็นต้องเป็นลูกโดยตรง

ทดสอบใน Firefox (23) และ Chrome (28)

หากคุณต้องการเลื่อนทั้งหน้าให้ตรวจสอบคำถามนี้


สิ่งที่เป็นelem?? คุณไม่ได้อธิบายเลย
vsync

คุณจะได้รับไมล์สะสมที่ดีกว่า / ไม่ขัดแย้งกันถ้าคุณแลกเปลี่ยน $ ใน fn.scrollTo เป็น jQuery แทน
Barry Carlyon

ข้อบกพร่องใหญ่หลวงในเรื่องนี้คุณไม่ได้มีขอบเขต: $(this).scrollTop($(this).scrollTop() - $(this).offset().top + $(elem, $(this)).offset().top);- ขอแสดงความนับถือ
Luke Snowden

1
หากคุณต้องการที่จะออกจากบางขอบบนระหว่างหน้าและองค์ประกอบ (ซึ่งอาจจะดูดีกว่าในบางกรณี) ลบเช่น 10px $(this).scrollTop() - $(this).offset().top + $(elem).offset().top - 10เช่น:
lepe

หากคุณมีความแตกต่างระหว่างตำแหน่ง Firefox และ Chrome (หรือเบราว์เซอร์อื่น ๆ ), ตรวจสอบรหัส html ของคุณ (ดูรายงานข้อผิดพลาดนี้ )
Lepe

34

ฉันได้ปรับคำตอบของ Glenn Moss ให้กับบัญชีเนื่องจาก div ส่วนเกินอาจไม่อยู่ที่ด้านบนของหน้า

parentDiv.scrollTop(parentDiv.scrollTop() + (innerListItem.position().top - parentDiv.position().top) - (parentDiv.height()/2) + (innerListItem.height()/2)  )

ฉันใช้สิ่งนี้ในแอปพลิเคชันแผนที่ google พร้อมด้วยแม่แบบที่ตอบสนอง ในความละเอียด> 800px รายการจะอยู่ทางด้านซ้ายของแผนที่ ในความละเอียด <800 รายการอยู่ด้านล่างแผนที่


6

คำตอบข้างต้นจะวางตำแหน่งองค์ประกอบภายในที่ด้านบนขององค์ประกอบล้นแม้ว่ามันจะอยู่ในมุมมองภายในองค์ประกอบล้น ฉันไม่ต้องการที่จะแก้ไขมันเพื่อไม่ให้เปลี่ยนตำแหน่งการเลื่อนถ้าองค์ประกอบอยู่ในมุมมอง

jQuery.fn.scrollTo = function(elem, speed) {
    var $this = jQuery(this);
    var $this_top = $this.offset().top;
    var $this_bottom = $this_top + $this.height();
    var $elem = jQuery(elem);
    var $elem_top = $elem.offset().top;
    var $elem_bottom = $elem_top + $elem.height();

    if ($elem_top > $this_top && $elem_bottom < $this_bottom) {
        // in view so don't do anything
        return;
    }
    var new_scroll_top;
    if ($elem_top < $this_top) {
        new_scroll_top = {scrollTop: $this.scrollTop() - $this_top + $elem_top};
    } else {
        new_scroll_top = {scrollTop: $elem_bottom - $this_bottom + $this.scrollTop()};
    }
    $this.animate(new_scroll_top, speed === undefined ? 100 : speed);
    return this;
};

สิ่งนี้ช่วยฉัน !! ดูstackoverflow.com/questions/48283932/…
ยีน b

1

ฉันเขียน 2 ฟังก์ชั่นเหล่านี้เพื่อทำให้ชีวิตของฉันง่ายขึ้น:

function scrollToTop(elem, parent, speed) {
    var scrollOffset = parent.scrollTop() + elem.offset().top;
    parent.animate({scrollTop:scrollOffset}, speed);
    // parent.scrollTop(scrollOffset, speed);
}

function scrollToCenter(elem, parent, speed) {
    var elOffset = elem.offset().top;
    var elHeight = elem.height();
    var parentViewTop = parent.offset().top;
    var parentHeight = parent.innerHeight();
    var offset;

    if (elHeight >= parentHeight) {
        offset = elOffset;
    } else {
        margin = (parentHeight - elHeight)/2;
        offset = elOffset - margin;
    }

    var scrollOffset = parent.scrollTop() + offset - parentViewTop;

    parent.animate({scrollTop:scrollOffset}, speed);
    // parent.scrollTop(scrollOffset, speed);
}

และใช้พวกเขา:

scrollToTop($innerListItem, $parentDiv, 200);
// or
scrollToCenter($innerListItem, $parentDiv, 200);

elem.offset().topกำลังคำนวณจากด้านบนของหน้าจอ ฉันต้องการคำนวณจากองค์ประกอบหลัก ฉันจะทำอย่างไร
Santosh

0

หลังจากเล่นไปนานมากนี่คือสิ่งที่ฉันคิดขึ้นมา:

    jQuery.fn.scrollTo = function (elem) {
        var b = $(elem);
        this.scrollTop(b.position().top + b.height() - this.height());
    };

และฉันเรียกมันว่าสิ่งนี้

$("#basketListGridHolder").scrollTo('tr[data-uid="' + basketID + '"]');
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.