ฉันจะทำให้องค์ประกอบเลื่อนดูได้อย่างไรโดยใช้ jQuery


169

ฉันมีเอกสาร HTML <ul><li><img...ที่มีภาพในรูปแบบตารางโดยใช้ หน้าต่างเบราว์เซอร์มีทั้งการเลื่อนแนวตั้งและแนวนอน

คำถาม: เมื่อฉันคลิกที่รูปภาพ<img>ฉันจะได้รับเอกสารทั้งหมดเพื่อเลื่อนไปยังตำแหน่งที่รูปภาพที่ฉันเพิ่งคลิกไปได้top:20px; left:20pxอย่างไร

ฉันมีการเรียกดูที่นี่สำหรับโพสต์ที่คล้ายกัน ... แม้ว่าฉันจะค่อนข้างใหม่กับ JavaScript และต้องการที่จะเข้าใจว่าสิ่งนี้ประสบความสำเร็จสำหรับฉันอย่างไร


คำตอบ:


192

เมื่อคุณต้องการทราบว่ามันทำงานอย่างไรฉันจะอธิบายทีละขั้นตอน

ก่อนอื่นคุณต้องผูกฟังก์ชั่นเป็นตัวจัดการการคลิกของภาพ:

$('#someImage').click(function () {
    // Code to do scrolling happens here
});

id="someImage"ที่จะนำไปใช้จัดการคลิกไปที่ภาพที่มี หากคุณต้องการที่จะทำเช่นนี้เพื่อทุกภาพแทนที่ด้วย'#someImage''img'

ตอนนี้สำหรับรหัสเลื่อนจริง:

  1. รับภาพออฟเซ็ต (สัมพันธ์กับเอกสาร):

    var offset = $(this).offset(); // Contains .top and .left
  2. ลบ 20 จากtopและleft:

    offset.left -= 20;
    offset.top -= 20;
  3. ตอนนี้ทำให้คุณสมบัติ CSS แบบเลื่อนขึ้นลงและเลื่อนซ้ายของ<body>และ<html>:

    $('html, body').animate({
        scrollTop: offset.top,
        scrollLeft: offset.left
    });

3
ใช้งานได้เฉพาะกับเค้าโครงที่เรียบง่าย มันไม่ได้จัดการกับทุกกรณีวิธีที่วิธี W3C .scrollIntoViewทำเมื่อองค์ประกอบซ้อนกันภายในคอนเทนเนอร์ล้นหลาย
natevw

2
ทำไมต้องบูรณาการล้อ Element.scrollIntoView(): developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
Serge

@Serge เพราะเป็นร่างที่ใช้งานได้ซึ่งไม่ได้นำไปใช้กับเบราว์เซอร์ทั้งหมด
John Smith

@ JohnSmith โปรดอ่านลิงค์ที่ฉันโพสต์อย่างระมัดระวังส่วน "ความเข้ากันได้ของเบราว์เซอร์" คุณจะเห็นว่าไม่มีเบราว์เซอร์ที่ไม่รองรับscrollIntoView
Serge

@Serge ขออภัยเกี่ยวกับสิ่งที่ฉันไม่ได้ตระหนักถึงนอกจากนี้ยังมี scrollIntoViewOption (ซึ่งเป็นสิ่งที่ไม่รองรับกว้างพอ) ฉันเดาว่ามันดีพอ
John Smith

377

มีวิธีการ DOM ที่เรียกว่าscrollIntoViewซึ่งสนับสนุนโดยเบราว์เซอร์หลักทั้งหมดที่จะจัดองค์ประกอบกับด้านบน / ซ้ายของวิวพอร์ต (หรือใกล้ที่สุดเท่าที่เป็นไปได้)

$("#myImage")[0].scrollIntoView();

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

$("#myImage")[0].scrollIntoView({
    behavior: "smooth", // or "auto" or "instant"
    block: "start" // or "end"
});

อีกทางเลือกหนึ่งถ้าองค์ประกอบทั้งหมดมี ID ที่ไม่ซ้ำกันคุณสามารถเปลี่ยนhashคุณสมบัติของlocationวัตถุสำหรับการสนับสนุนปุ่มย้อนกลับ / ไปข้างหน้า:

$(document).delegate("img", function (e) {
    if (e.target.id)
        window.location.hash = e.target.id;
});

หลังจากนั้นเพียงปรับscrollTop/ scrollLeftproperties โดย -20:

document.body.scrollLeft -= 20;
document.body.scrollTop -= 20;

2
ขอบคุณ! 5 บทความ SO อื่น ๆ และคุณจับมันได้อย่างสมบูรณ์แบบ กรณีการใช้งานของฉันคือคอนเทนเนอร์ในกล่องโต้ตอบการบูตที่ต้องการเลื่อนดู
Stephen Patten

10
ตามหมายเหตุ: $("#myImage")[0].scrollIntoView(false);จะจัดตำแหน่งองค์ประกอบที่ด้านล่างของหน้าต่าง
ฟิลิปป์

1
ระวัง: พฤติกรรม "ราบรื่น" ไม่ได้รับการสนับสนุนอย่างกว้างขวางและscrollIntoViewอาจเป็นประสบการณ์ที่สับสนสำหรับผู้ใช้ที่ไม่มีภาพเคลื่อนไหวบางประเภท
Cody Duval

1
@JohnHenckel: ไม่ถูกต้องแม้แต่ IE 5.5 ก็scrollIntoViewมีพารามิเตอร์บูลีน ฉันจะลองและส่งคำขอดึงสำหรับ caniuse.com ในภายหลัง
Andy E

1
หมายเหตุ: เมื่อใช้ Chrome ฉันไม่สามารถเลื่อน<td>องค์ประกอบไปยังมุมมองได้แทนที่จะต้องเลื่อนพาเรนต์ ( <tr>) และใช้งานได้
CrazyTim

13

ทางออกที่ง่ายที่สุดที่ฉันเคยเห็น

var offset = $("#target-element").offset();
$('html, body').animate({
    scrollTop: offset.top,
    scrollLeft: offset.left
}, 1000);

สอนที่นี่


ด้วยความเสี่ยงที่จะทำให้มันง่ายขึ้นฉันได้แก้ไขสิ่งนี้เพื่อรองรับการเลื่อนในแนวนอนเช่นกัน
jpaugh

7

มีวิธีการเลื่อนองค์ประกอบลงในมุมมองโดยตรง แต่ถ้าคุณต้องการเลื่อนไปยังจุดสัมพันธ์จากองค์ประกอบคุณต้องทำด้วยตนเอง:

ภายในตัวจัดการการคลิกรับตำแหน่งขององค์ประกอบที่สัมพันธ์กับเอกสารการลบ20และการใช้window.scrollTo:

var pos = $(this).offset();
var top = pos.top - 20;
var left = pos.left - 20;
window.scrollTo((left < 0 ? 0 : left), (top < 0 ? 0 : top));

7

ลองดูที่ปลั๊กอินjQuery.scrollTo นี่คือการสาธิต

ปลั๊กอินนี้มีตัวเลือกมากมายที่เหนือกว่าscrollIntoView ดั้งเดิมคุณ ตัวอย่างเช่นคุณสามารถตั้งค่าการเลื่อนให้เรียบแล้วตั้งค่าการโทรกลับเมื่อการเลื่อนเสร็จสิ้น

นอกจากนี้คุณยังสามารถมีลักษณะที่ทุกปลั๊กอิน JQuery tagged with "เลื่อน"


ฉันได้รับการลด / ตำแหน่งที่แตกต่างกันในทุกเบราว์เซอร์ในกรณีของฉันและปลั๊กอินนี้ช่วยแก้ไขให้ฉันด้วย! ขอบคุณ!
LaurelB

4

นี่คือปลั๊กอิน jQuery ฉบับย่อในการแมปฟังก์ชันการทำงานของเบราว์เซอร์ในตัว:

$.fn.ensureVisible = function () { $(this).each(function () { $(this)[0].scrollIntoView(); }); };

...

$('.my-elements').ensureVisible();

3

หลังจากลองผิดลองถูกฉันก็ใช้ฟังก์ชั่นนี้ทำงานร่วมกับ iframe ด้วย

function bringElIntoView(el) {    
    var elOffset = el.offset();
    var $window = $(window);
    var windowScrollBottom = $window.scrollTop() + $window.height();
    var scrollToPos = -1;
    if (elOffset.top < $window.scrollTop()) // element is hidden in the top
        scrollToPos = elOffset.top;
    else if (elOffset.top + el.height() > windowScrollBottom) // element is hidden in the bottom
        scrollToPos = $window.scrollTop() + (elOffset.top + el.height() - windowScrollBottom);
    if (scrollToPos !== -1)
        $('html, body').animate({ scrollTop: scrollToPos });
}

2

เพียงแค่ปลาย ทำงานกับ Firefox เท่านั้น

Element.scrollIntoView ();


4
สิ่งนี้ใช้ได้กับเบราว์เซอร์ทั้งหมดที่มีพารามิเตอร์บูลีนหรือไม่มีพารามิเตอร์เลย สนับสนุนเฉพาะพารามิเตอร์วัตถุขั้นสูงเพิ่มเติมเท่านั้น
Risord

ตามdeveloper.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewมีการขาดการสนับสนุนเบราว์เซอร์ทั่วไป
lfender6445

ตอนนี้รองรับได้อย่างเพียงพอเท่านั้น Opera Mini: caniuse.com/#search=scrollIntoView
John Magnolia

มีโพลีฟิลน้ำหนักเบาจำนวนมากอยู่ในนั้น
Martin James

1

UI ของฉันมีรายการเลื่อนนิ้วโป้งในแนวตั้งภายใน thumbbar เป้าหมายคือเพื่อให้ใช้หัวแม่มือปัจจุบันตรงกลางของ thumbbar ฉันเริ่มจากคำตอบที่ได้รับอนุมัติแล้ว แต่พบว่ามีการปรับแต่งเล็กน้อยเพื่อให้นิ้วหัวแม่มือตรงกลางเป็นจริง หวังว่านี่จะช่วยคนอื่นได้

มาร์กอัป:

<ul id='thumbbar'>
    <li id='thumbbar-123'></li>
    <li id='thumbbar-124'></li>
    <li id='thumbbar-125'></li>
</ul>

jQuery:

// scroll the current thumb bar thumb into view
heightbar   = $('#thumbbar').height();
heightthumb = $('#thumbbar-' + pageid).height();
offsetbar   = $('#thumbbar').scrollTop();


$('#thumbbar').animate({
    scrollTop: offsetthumb.top - heightbar / 2 - offsetbar - 20
});

0

2 ขั้นตอนง่าย ๆ สำหรับการเลื่อนลงไปที่ปลายหรือล่าง

ขั้นที่ 1: รับ div เต็มความสูง (การสนทนา) ที่เลื่อนได้

ขั้นที่ 2: ใช้ scrollTop บน div ที่สามารถเลื่อนได้ (การสนทนา) โดยใช้ค่าที่ได้รับในขั้นตอนที่ 1

var fullHeight = $('#conversation')[0].scrollHeight;

$('#conversation').scrollTop(fullHeight);

ขั้นตอนข้างต้นจะต้องใช้สำหรับทุกภาคผนวกของ div การสนทนา


0

หลังจากพยายามหาวิธีแก้ปัญหาที่จัดการทุกสถานการณ์ (ตัวเลือกสำหรับการเคลื่อนไหวการเลื่อนการเติมรอบวัตถุเมื่อมันเลื่อนเข้ามาดูการทำงานแม้ในสถานการณ์ที่คลุมเครือเช่นใน iframe) ในที่สุดฉันก็เลยเขียนโซลูชันของตัวเองขึ้นมา เนื่องจากดูเหมือนว่าจะใช้งานได้เมื่อโซลูชันอื่น ๆ ล้มเหลวฉันจึงคิดว่าจะแบ่งปัน:

function scrollIntoViewIfNeeded($target, options) {

    var options = options ? options : {},
    $win = $($target[0].ownerDocument.defaultView), //get the window object of the $target, don't use "window" because the element could possibly be in a different iframe than the one calling the function
    $container = options.$container ? options.$container : $win,        
    padding = options.padding ? options.padding : 20,
    elemTop = $target.offset().top,
    elemHeight = $target.outerHeight(),
    containerTop = $container.scrollTop(),
    //Everything past this point is used only to get the container's visible height, which is needed to do this accurately
    containerHeight = $container.outerHeight(),
    winTop = $win.scrollTop(),
    winBot = winTop + $win.height(),
    containerVisibleTop = containerTop < winTop ? winTop : containerTop,
    containerVisibleBottom = containerTop + containerHeight > winBot ? winBot : containerTop + containerHeight,
    containerVisibleHeight = containerVisibleBottom - containerVisibleTop;

    if (elemTop < containerTop) {
        //scroll up
        if (options.instant) {
            $container.scrollTop(elemTop - padding);
        } else {
            $container.animate({scrollTop: elemTop - padding}, options.animationOptions);
        }
    } else if (elemTop + elemHeight > containerTop + containerVisibleHeight) {
        //scroll down
        if (options.instant) {
            $container.scrollTop(elemTop + elemHeight - containerVisibleHeight + padding);
        } else {
            $container.animate({scrollTop: elemTop + elemHeight - containerVisibleHeight + padding}, options.animationOptions);
        }
    }
}

$target เป็นวัตถุ jQuery ที่มีวัตถุที่คุณต้องการเลื่อนดูถ้าจำเป็น

options (เป็นทางเลือก) สามารถมีตัวเลือกต่อไปนี้ผ่านในวัตถุ:

options.$container- วัตถุ jQuery ที่ชี้ไปยังองค์ประกอบที่มี $ target (กล่าวอีกนัยหนึ่งคือองค์ประกอบใน Dom ด้วยแถบเลื่อน) เริ่มต้นไปที่หน้าต่างที่มีองค์ประกอบ $ target และฉลาดพอที่จะเลือกหน้าต่าง iframe อย่าลืมใส่ $ ในชื่อคุณสมบัติ

options.padding- ช่องว่างภายในเป็นพิกเซลเพื่อเพิ่มด้านบนหรือด้านล่างของวัตถุเมื่อเลื่อนลงในมุมมอง ด้วยวิธีนี้มันไม่ถูกต้องกับขอบของหน้าต่าง ค่าเริ่มต้นถึง 20

options.instant- หากตั้งค่าเป็นจริงจะไม่ใช้ jQuery animate และการเลื่อนจะปรากฏขึ้นในตำแหน่งที่ถูกต้องทันที ค่าเริ่มต้นเป็นเท็จ

options.animationOptions- ตัวเลือก jQuery ใด ๆ ที่คุณต้องการส่งต่อไปยังฟังก์ชัน jQuery animate (ดูที่http://api.jquery.com/animate/ ) ด้วยสิ่งนี้คุณสามารถเปลี่ยนระยะเวลาของภาพเคลื่อนไหวหรือมีฟังก์ชั่นการโทรกลับเมื่อดำเนินการเลื่อนเสร็จสมบูรณ์ ใช้งานได้options.instantก็ต่อเมื่อตั้งค่าเป็นเท็จ หากคุณต้องการที่จะมีการเคลื่อนไหวทันที แต่มีการเรียกกลับตั้งแทนการใช้options.animationOptions.duration = 0options.instant = true

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