Bagaimana cara saya menggulir ke elemen dalam Div yang meluap?

159

Saya memiliki 20 item daftar di dalam div yang hanya dapat menampilkan 5 item sekaligus. Apa cara yang baik untuk menggulir ke item # 10, dan kemudian item # 20? Saya tahu ketinggian semua barang.

The scrollToPlugin melakukan hal ini, tetapi sumbernya tidak super mudah dipahami tanpa benar-benar masuk ke dalamnya. Saya tidak ingin menggunakan plugin ini.

Katakanlah saya memiliki fungsi yang mengambil 2 elemen $parentDiv, $innerListItem, tidak $innerListItem.offset().topjuga $innerListItem.positon().topmemberi saya scrollTop benar untuk $ parentDiv.

mkoryak
sumber
Menghapus jawaban saya karena pembaruan Anda. Tapi percayalah, setelah memiliki sikap yang sama sebelumnya, ada banyak kebiasaan browser dengan posisi dan margin, dll ... plugin adalah rute yang jauh lebih sederhana dan lebih hemat waktu, dan hanya 3k sebelum GZip.
Nick Craver
1
Tetap gunakan plugin scrollTo. Itu tidak sulit. $("#container").scrollTo(target, duration, options). Target hanyalah sebuah #anchor. Selesai
Ryan McGeary
sepertinya harus ada pengetahuan di luar sana untuk melakukan ini tanpa plugin. besok sakit mulai membaca sumber
mkoryak
5
@mkoryak - Pengetahuannya ada di luar sana, tetapi ketika Anda menghitung peramban yang aneh, pada dasarnya Anda berakhir dengan ... plugin .scrollTo , jadi mengapa harus menemukan kembali kemudi sepanjang waktu?
Nick Craver
1
IMHO, Anda mungkin akan berakhir dengan subset yang tepat dari apa yang Anda butuhkan dari .scrollTo hari ini . Tetapi dalam waktu beberapa bulan, sementara .scrollTo telah diperbarui ke IE9, FF4 dan Chrome 6, Anda harus memulai dari awal ... 3k sepertinya harga yang sangat rendah untuk menghindari hal ini.
Wim

Jawaban:

236

Ini $innerListItem.position().topsebenarnya relatif terhadap .scrollTop()leluhur pertama yang diposisikan. Jadi cara untuk menghitung nilai yang benar $parentDiv.scrollTop()adalah dengan memulai dengan memastikan bahwa $parentDivdiposisikan. Jika belum memiliki eksplisit position, gunakan position: relative. Unsur-unsur $innerListItemdan semua leluhurnya hingga $parentDivperlu tidak memiliki posisi eksplisit. Sekarang Anda dapat menggulir ke $innerListItemdengan:

// 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);
Glenn Moss
sumber
152

Ini adalah plugin saya sendiri (akan memposisikan elemen di atas daftar. Khusus untuk overflow-y : auto. Mungkin tidak bekerja dengan overflow-x!):

CATATAN : elemadalah pemilih HTML elemen tempat halaman akan digulirkan. Apa pun didukung oleh jQuery, seperti: #myid, div.myclass, $(jquery object), [object dom], dll

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

Jika Anda tidak perlu dianimasikan, gunakan:

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

Cara Penggunaan:

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

Catatan: #innerItembisa di mana saja di dalam #overflow_div. Tidak harus menjadi anak langsung.

Diuji dalam Firefox (23) dan Chrome (28).

Jika Anda ingin menggulir seluruh halaman, periksa pertanyaan ini .

lepe
sumber
apa itu elem?? Anda tidak menjelaskannya sama sekali.
vsync
Anda mendapatkan jarak tempuh yang lebih baik / bukan konflik jika Anda menukar $ di fn.scrollUntuk ke jQuery sebagai gantinya
Barry Carlyon
Kelemahan besar dengan ini, Anda tidak mengandung ruang lingkup: $(this).scrollTop($(this).scrollTop() - $(this).offset().top + $(elem, $(this)).offset().top);- salam
Luke Snowden
1
Jika Anda ingin meninggalkan beberapa margin atas antara halaman dan elemen (yang mungkin terlihat lebih baik dalam beberapa kasus), mengurangi, misalnya, 10px, seperti: $(this).scrollTop() - $(this).offset().top + $(elem).offset().top - 10.
lepe
Jika Anda memiliki perbedaan posisi antara Firefox dan Chrome (atau browser lain), periksa kode html Anda (lihat laporan bug ini )
lepe
34

Saya telah menyesuaikan jawaban Glenn Moss untuk memperhitungkan fakta bahwa overflow div mungkin tidak ada di bagian atas halaman.

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

Saya menggunakan ini pada aplikasi google maps dengan templat responsif. Pada resolusi> 800px, daftar berada di sisi kiri peta. Pada resolusi <800 daftar berada di bawah peta.

KPheasey
sumber
6

Jawaban di atas akan memposisikan elemen dalam di bagian atas elemen overflow bahkan jika itu terlihat di dalam elemen overflow. Saya tidak ingin itu jadi saya memodifikasinya untuk tidak mengubah posisi gulir jika elemen tersebut terlihat.

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;
};
mike
sumber
Ini membantu saya !! Lihat stackoverflow.com/questions/48283932/…
gen b.
1

Saya menulis 2 fungsi ini untuk membuat hidup saya lebih mudah:

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

Dan gunakan mereka:

scrollToTop($innerListItem, $parentDiv, 200);
// or
scrollToCenter($innerListItem, $parentDiv, 200);
minum
sumber
elem.offset().topsedang menghitung dari bagian atas layar. Saya ingin itu menghitung dari elemen induk. Bagaimana aku melakukan itu ?
Santosh
0

Setelah bermain dengannya untuk waktu yang sangat lama, inilah yang saya pikirkan:

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

dan saya menyebutnya seperti ini

$("#basketListGridHolder").scrollTo('tr[data-uid="' + basketID + '"]');
bruce reeves
sumber