Come scorrere fino a un elemento all'interno di un Div overflow?


159

Ho 20 voci di elenco all'interno di un div che possono mostrarne solo 5 alla volta. Qual è un buon modo per scorrere fino all'elemento # 10 e quindi all'articolo # 20? Conosco l'altezza di tutti gli oggetti.

Il scrollToplugin fa questo, ma la sua fonte non è super facile da capire senza davvero entrarci. Non voglio usare questo plugin.

Diciamo che ho una funzione che prende 2 elementi $parentDiv, $innerListItem$innerListItem.offset().top$innerListItem.positon().topmi dà la giusta scrollTop per $ parentDiv.


Rimossa la mia risposta a causa del tuo aggiornamento. Ma credetemi, avendo avuto lo stesso atteggiamento prima, ci sono molte stranezze del browser con posizione e margini, ecc ... il plugin è un percorso molto più semplice e richiede meno tempo, e solo 3k prima di GZip.
Nick Craver

1
Usa comunque il plugin scrollTo. Non è difficile. $("#container").scrollTo(target, duration, options). L'obiettivo è solo un #anchor. Fatto.
Ryan McGeary,

sembra che ci dovrebbe essere conoscenza là fuori per farlo senza un plugin. domani inizierò a leggere la fonte
mkoryak,

5
@mkoryak - La conoscenza è là fuori, ma quando si tiene conto delle stranezze del browser, praticamente si finisce con ... il plug-in .scrollTo , quindi perché reinventare continuamente la ruota?
Nick Craver

1
IMHO, probabilmente finirai con il sottoinsieme esatto di quello che ti serve da .scrollTo oggi . Ma tra qualche mese, mentre .scrollTo è stato aggiornato a IE9, FF4 e Chrome 6, dovrai ricominciare da capo ... 3k sembra un prezzo molto basso per evitarlo.
Mercoledì

Risposte:


236

In $innerListItem.position().toprealtà è relativo al .scrollTop()suo primo antenato posizionato. Quindi il modo per calcolare il $parentDiv.scrollTop()valore corretto è iniziare assicurandosi che $parentDivsia posizionato. Se non ha già un esplicito position, utilizzare position: relative. Gli elementi $innerListIteme tutti i suoi antenati $parentDivdevono avere una posizione esplicita. Ora puoi scorrere fino a $innerListItemcon:

// 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

Questo è il mio plugin (posizionerà l'elemento in cima all'elenco. Specialmente per overflow-y : auto. Potrebbe non funzionare con overflow-x!):

NOTA : elemè il selettore HTML di un elemento su cui verrà scorrere la pagina. Nulla supportato da jQuery, come: #myid, div.myclass, $(jquery object), [oggetto dom], etc.

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

Se non ti serve che sia animato, usa:

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

Come usare:

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

Nota: #innerItempuò essere ovunque all'interno #overflow_div. Non deve essere davvero un bambino diretto.

Testato su Firefox (23) e Chrome (28).

Se vuoi scorrere l'intera pagina, controlla questa domanda .


cos'è elem?? non lo spieghi affatto.
vsync,

Otterrai un miglior chilometraggio / non conflitto se si scambia $ in fn.scroll, invece di jQuery
Barry Carlyon,

Grande difetto con questo, non contiene lo scopo: $(this).scrollTop($(this).scrollTop() - $(this).offset().top + $(elem, $(this)).offset().top);- saluti
Luke Snowden,

1
Se si desidera lasciare un po 'di margine superiore tra la pagina e l'elemento (che può guardare meglio in alcuni casi), sottrarre, per esempio, 10px, come: $(this).scrollTop() - $(this).offset().top + $(elem).offset().top - 10.
lepe,

Se stai riscontrando differenze di posizione tra Firefox e Chrome (o altri browser), controlla il tuo codice html (vedi questo bug report )
lepe

34

Ho modificato la risposta di Glenn Moss per tenere conto del fatto che il div di overflow potrebbe non essere nella parte superiore della pagina.

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

Lo stavo usando su un'applicazione google maps con un modello reattivo. Con una risoluzione> 800 px, l'elenco era sul lato sinistro della mappa. Alla risoluzione <800 l'elenco era sotto la mappa.


6

Le risposte sopra posizioneranno l'elemento interno nella parte superiore dell'elemento overflow anche se è in vista all'interno dell'elemento overflow. Non volevo, quindi l'ho modificato per non cambiare la posizione di scorrimento se l'elemento è in vista.

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

Questo mi ha aiutato !! Vedi stackoverflow.com/questions/48283932/…
gene b.

1

Scrivo queste 2 funzioni per semplificarmi la vita:

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

E usali:

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

elem.offset().topsta calcolando dalla parte superiore dello schermo. Voglio che calcoli dall'elemento genitore. Come lo faccio ?
Santosh,

0

Dopo averci giocato per molto tempo, questo è quello che mi è venuto in mente:

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

e lo chiamo così

$("#basketListGridHolder").scrollTo('tr[data-uid="' + basketID + '"]');
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.