Bagaimana cara mendapatkan elemen untuk menggulir ke tampilan, menggunakan jQuery?

169

Saya memiliki dokumen HTML dengan gambar dalam format grid menggunakan <ul><li><img.... Jendela browser memiliki pengguliran vertikal & horizontal.

Pertanyaan: Ketika saya mengklik suatu gambar<img> , bagaimana cara mendapatkan seluruh dokumen untuk menggulir ke posisi di mana gambar yang baru saja saya klik top:20px; left:20px?

Saya sudah menelusuri di sini untuk posting serupa ... meskipun saya cukup baru untuk JavaScript, dan ingin memahami bagaimana ini dicapai untuk diri saya sendiri.

Nasir
sumber

Jawaban:

192

Karena Anda ingin tahu cara kerjanya, saya akan menjelaskannya selangkah demi selangkah.

Pertama Anda ingin mengikat fungsi sebagai pengendali klik gambar:

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

Itu akan menerapkan penangan klik ke gambar dengan id="someImage". Jika Anda ingin melakukan ini untuk semua gambar, ganti '#someImage'dengan 'img'.

Sekarang untuk kode gulir yang sebenarnya:

  1. Dapatkan offset gambar (relatif terhadap dokumen):

    var offset = $(this).offset(); // Contains .top and .left
  2. Kurangi 20 dari topdan left:

    offset.left -= 20;
    offset.top -= 20;
  3. Sekarang hidupkan properti CSS scroll-top dan scroll-left dari <body>dan <html>:

    $('html, body').animate({
        scrollTop: offset.top,
        scrollLeft: offset.left
    });
David Tang
sumber
3
Ini hanya berfungsi untuk tata letak sederhana. Itu tidak menangani semua kasus seperti .scrollIntoViewmetode W3C lakukan ketika elemen bersarang dalam beberapa wadah yang meluap.
natevw
2
mengapa harus menemukan kembali roda? Element.scrollIntoView(): developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
Serge
@Serge karena ini adalah konsep kerja yang belum diimplementasikan di semua browser
John Smith
@JohnSmith harap baca dengan seksama tautan yang saya pasang, bagian "Kompatibilitas Browser", Anda akan melihat tidak ada browser yang tidak mendukungscrollIntoView
Serge
@Serge Maaf tentang itu, saya tidak menyadari, ada juga scrollIntoViewOption (yang merupakan salah satu yang tidak didukung cukup lebar). Saya kira itu cukup baik.
John Smith
377

Ada metode DOM yang disebut scrollIntoView, yang didukung oleh semua browser utama, yang akan menyelaraskan elemen dengan bagian atas / kiri viewport (atau sedekat mungkin).

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

Pada browser yang didukung, Anda dapat memberikan opsi:

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

Atau, jika semua elemen memiliki ID unik, Anda bisa mengubah hashproperti locationobjek untuk dukungan tombol maju / mundur:

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

Setelah itu, cukup sesuaikan scrollTop/ scrollLeftproperties dengan -20:

document.body.scrollLeft -= 20;
document.body.scrollTop -= 20;
Andy E
sumber
2
Terima kasih! 5 artikel SO lainnya dan Anda memakukannya dengan sempurna. Kasing saya adalah wadah dalam dialog bootstrap yang perlu digulir ke tampilan.
Stephen Patten
10
Sebagai catatan: $("#myImage")[0].scrollIntoView(false);akan menyelaraskan elemen di bagian bawah jendela.
Philipp
1
Hati-hati: perilaku "mulus" tidak didukung secara luas, dan scrollIntoViewdapat menjadi pengalaman yang membingungkan bagi pengguna tanpa semacam animasi.
Cody Duval
1
@ JohnHenckel: itu tidak benar, bahkan IE 5.5 memiliki scrollIntoViewdengan parameter boolean. Saya akan mencoba dan mengirim permintaan tarik untuk caniuse.com nanti.
Andy E
1
Catatan: Menggunakan Chrome, saya tidak dapat menggulir <td>elemen ke tampilan, melainkan harus menggulir orang tua mereka ( <tr>) dan itu berhasil.
CrazyTim
13

Solusi paling sederhana yang pernah saya lihat

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

Tutorial Di Sini

Matt Watson
sumber
Dengan risiko membuatnya menjadi lebih sederhana, saya mengedit ini untuk mendukung pengguliran horizontal juga.
jpaugh
7

Ada metode untuk menggulir elemen langsung ke tampilan, tetapi jika Anda ingin menggulir ke titik relatif dari suatu elemen, Anda harus melakukannya secara manual:

Di dalam handler klik, dapatkan posisi elemen relatif terhadap dokumen, kurangi 20dan gunakan 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));
Felix Kling
sumber
7

Lihatlah plugin jQuery.scrollTo . Ini demo .

Plugin ini memiliki banyak opsi yang melampaui apa yang ditawarkan scrollIntoView asli kepada Anda. Misalnya, Anda dapat mengatur pengguliran agar menjadi lancar, dan kemudian mengatur panggilan balik untuk saat pengguliran selesai.

Anda juga dapat melihat semua plugin JQuery yang ditandai dengan "gulir" .

Rob Stevenson-Leggett
sumber
Saya mendapatkan offset / posisi berbeda di setiap browser dalam kasus saya, dan plugin ini membantu memperbaikinya untuk saya! Terima kasih!
LaurelB
4

Berikut ini adalah plugin jQuery cepat untuk memetakan fungsionalitas browser bawaan dengan baik:

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

...

$('.my-elements').ensureVisible();
rampok
sumber
3

Setelah coba-coba saya menemukan fungsi ini, berfungsi dengan iframe juga.

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 });
}
Nada Soda
sumber
2

Hanya sebuah tip. Hanya bekerja pada firefox

Element.scrollIntoView ();

murid wp
sumber
4
Ini berfungsi untuk semua browser dengan parameter boolean atau tanpa parameter sama sekali. Hanya parameter objek yang lebih maju yang kurang didukung.
Risord
menurut developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView, secara umum tidak ada dukungan browser untuk ini
lfender6445
Sekarang cukup baik hanya didukung Opera Mini: caniuse.com/#search=scrollIntoView
John Magnolia
Ada sejumlah polyfill yang sangat ringan di luar sana.
Martin James
1

UI saya memiliki daftar gulir jempol vertikal di dalam thumbbar. Tujuannya adalah untuk membuat ibu jari saat ini tepat di tengah-tengah thumbbar. Saya mulai dari jawaban yang disetujui, tetapi menemukan bahwa ada beberapa penyesuaian untuk benar-benar memusatkan ibu jari saat ini. Semoga ini bisa membantu orang lain.

markup:

<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
});
xeo
sumber
0

Sederhana 2 langkah untuk menggulir ke bawah atau ke bawah.

Langkah 1: dapatkan ketinggian penuh dari scroll (percakapan) div.

Langkah 2: terapkan scrollTop pada div (percakapan) yang dapat digulir menggunakan nilai yang diperoleh di langkah1.

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

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

Langkah-langkah di atas harus diterapkan untuk setiap penambahan pada div percakapan.

Shiva Kumar P
sumber
0

Setelah mencoba menemukan solusi yang menangani setiap keadaan (opsi untuk menghidupkan gulir, melapisi objek setelah digulirkan ke tampilan, bekerja bahkan dalam keadaan yang tidak jelas seperti dalam iframe), akhirnya saya menulis solusi sendiri untuk ini. Karena tampaknya berfungsi ketika banyak solusi lain gagal, saya pikir saya akan membagikannya:

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 adalah objek jQuery yang berisi objek yang ingin Anda gulir ke tampilan jika diperlukan.

options (opsional) dapat berisi opsi berikut yang dilewatkan dalam suatu objek:

options.$container- objek jQuery yang menunjuk ke elemen yang mengandung $ target (dengan kata lain, elemen dalam dom dengan scrollbar). Default ke jendela yang berisi elemen $ target dan cukup pintar untuk memilih jendela iframe. Ingatlah untuk memasukkan $ dalam nama properti.

options.padding- bantalan dalam piksel untuk ditambahkan di atas atau di bawah objek saat digulir ke tampilan. Dengan cara ini tidak tepat di tepi jendela. Default ke 20.

options.instant- jika disetel ke true, jQuery animate tidak akan digunakan dan gulir akan langsung muncul ke lokasi yang benar. Default ke false.

options.animationOptions- opsi jQuery apa pun yang ingin Anda sampaikan ke fungsi animate jQuery (lihat http://api.jquery.com/animate/ ). Dengan ini, Anda dapat mengubah durasi animasi atau menjalankan fungsi panggilan balik ketika gulir selesai. Ini hanya berfungsi jika options.instantdisetel ke false. Jika Anda perlu memiliki animasi instan tetapi dengan panggilan balik, atur options.animationOptions.duration = 0alih-alih menggunakan options.instant = true.

dallin
sumber