Come faccio a ottenere un elemento per scorrere in vista, usando jQuery?


169

Ho un documento HTML con immagini in formato griglia usando <ul><li><img.... La finestra del browser presenta scorrimento sia verticale che orizzontale.

Domanda: quando faccio clic su un'immagine <img>, come faccio a far scorrere l'intero documento in una posizione in cui si trova l'immagine su cui ho appena fatto clic top:20px; left:20px?

Ho cercato qui per post simili ... anche se sono abbastanza nuovo su JavaScript e voglio capire come questo è realizzato da solo.


Risposte:


192

Dal momento che vuoi sapere come funziona, te lo spiego passo dopo passo.

Per prima cosa vuoi associare una funzione come gestore di clic dell'immagine:

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

Ciò applicherà il gestore di clic a un'immagine con id="someImage". Se vuoi fare questo per tutte le immagini, sostituiscile '#someImage'con 'img'.

Ora per l'attuale codice di scorrimento:

  1. Ottieni gli offset dell'immagine (rispetto al documento):

    var offset = $(this).offset(); // Contains .top and .left
  2. Sottrai 20 da tope left:

    offset.left -= 20;
    offset.top -= 20;
  3. Ora animare le proprietà CSS scroll-top e scroll-left di <body>e <html>:

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

3
Funziona solo con layout semplici. Non gestisce tutti i casi come fa il .scrollIntoViewmetodo W3C quando gli elementi sono nidificati in più contenitori di overflow.
natevw,

2
perché reinventare la ruota? Element.scrollIntoView(): developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
Serge

@Serge perché è una bozza funzionante che non è stata implementata in tutti i browser
John Smith

@JohnSmith per favore leggi attentamente il link che ho pubblicato, la sezione "Compatibilità del browser", vedrai che non esiste un browser che non supporta ilscrollIntoView
Serge

@Serge Mi dispiace, non me ne sono reso conto, c'era anche scrollIntoViewOption (che è quello che non è abbastanza supportato). Immagino sia abbastanza buono.
John Smith,

377

C'è un metodo DOM chiamato scrollIntoView, che è supportato da tutti i principali browser, che allineerà un elemento con la parte superiore / sinistra della finestra (o il più vicino possibile).

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

Sui browser supportati, è possibile fornire opzioni:

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

In alternativa, se tutti gli elementi hanno ID univoci, puoi semplicemente modificare la hashproprietà locationdell'oggetto per il supporto dei pulsanti avanti / indietro:

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

Successivamente, regola le proprietà scrollTop/ scrollLeftdi -20:

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

2
Grazie! 5 altri articoli SO e l'hai inchiodato perfettamente. Il mio caso d'uso era un contenitore in una finestra di dialogo bootstrap che doveva scorrere in vista.
Stephen Patten,

10
Come nota: $("#myImage")[0].scrollIntoView(false);allinea l'elemento nella parte inferiore della finestra.
Philipp,

1
Attenzione: il comportamento "liscio" non è ampiamente supportato e scrollIntoViewpuò essere un'esperienza confusa per gli utenti senza una sorta di animazione.
Cody Duval,

1
@JohnHenckel: non è corretto, anche IE 5.5 aveva scrollIntoViewcon il parametro booleano. Proverò a inviare una richiesta pull per caniuse.com più tardi.
Andy E

1
Nota: usando Chrome, non ho potuto scorrere gli <td>elementi in vista, invece ho dovuto scorrere i loro genitori ( <tr>) e ha funzionato.
CrazyTim

13

La soluzione più semplice che abbia mai visto

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

Tutorial qui


A rischio di renderlo meno semplice, l'ho modificato per supportare anche lo scorrimento orizzontale.
jpaugh

7

Esistono metodi per scorrere l'elemento direttamente nella vista, ma se vuoi scorrere fino a un punto relativo da un elemento, devi farlo manualmente:

All'interno del gestore di clic, ottieni la posizione dell'elemento rispetto al documento, sottrai 20e usa 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

Dai un'occhiata al plugin jQuery.scrollTo . Ecco una demo .

Questo plugin ha molte opzioni che vanno oltre a scrollIntoView nativo offre . Ad esempio, è possibile impostare lo scorrimento su liscio, quindi impostare una richiamata per quando lo scorrimento termina.

Puoi anche dare un'occhiata a tutti i plugin JQuery taggati con "scroll" .


Stavo ottenendo diversi offset / posizioni in ogni browser nel mio caso, e questo plugin mi ha aiutato a risolverlo! Grazie!
LaurelB,

4

Ecco un rapido plugin jQuery per mappare bene la funzionalità del browser integrata:

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

...

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

3

Dopo tentativi ed errori mi è venuta in mente questa funzione, funziona anche con 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

Solo un consiglio Funziona solo su Firefox

Element.scrollIntoView ();


4
Questo funziona per tutti i browser con parametro booleano o nessun parametro. Solo i parametri oggetto più avanzati sono meno supportati.
Risord,

secondo developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView vi è una generale mancanza di supporto per il browser per questo
lfender6445

Ora è abbastanza ben supportato solo Opera Mini: caniuse.com/#search=scrollIntoView
John Magnolia

C'è un numero di polyfill molto leggeri là fuori per questo.
Martin James,

1

La mia interfaccia utente ha un elenco a scorrimento verticale di pollici all'interno di una barra del thumar L'obiettivo era quello di rendere il pollice corrente proprio al centro della barra del thum. Ho iniziato dalla risposta approvata, ma ho scoperto che c'erano alcune modifiche per centrare veramente il pollice attuale. spero che questo aiuti qualcun altro.

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

0

Semplici 2 passaggi per scorrere verso il basso fino alla fine o in basso.

Step1: ottieni tutta l'altezza del div scorrevole (conversazione).

Step2: applica scrollTop su quel div scorrevole (conversazione) usando il valore ottenuto nel step1.

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

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

I passaggi precedenti devono essere applicati per ogni append sul div della conversazione.


0

Dopo aver cercato di trovare una soluzione che gestisse ogni circostanza (opzioni per l'animazione del rotolo, il riempimento attorno all'oggetto una volta che scorre in vista, funziona anche in circostanze oscure come in un iframe), ho finalmente finito per scrivere la mia soluzione per questo. Dal momento che sembra funzionare quando molte altre soluzioni falliscono, ho pensato di condividerlo:

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 è un oggetto jQuery contenente l'oggetto che si desidera scorrere in vista se necessario.

options (facoltativo) può contenere le seguenti opzioni passate in un oggetto:

options.$container- un oggetto jQuery che punta all'elemento contenente $ target (in altre parole, l'elemento nel dom con le barre di scorrimento). Il valore predefinito è la finestra che contiene l'elemento $ target ed è abbastanza intelligente da selezionare una finestra iframe. Ricorda di includere $ nel nome della proprietà.

options.padding- il riempimento in pixel da aggiungere sopra o sotto l'oggetto quando viene fatto scorrere in vista. In questo modo non è proprio contro il bordo della finestra. Il valore predefinito è 20.

options.instant- se impostato su true, jQuery animate non verrà utilizzato e lo scorrimento apparirà immediatamente nella posizione corretta. Il valore predefinito è false.

options.animationOptions- eventuali opzioni jQuery che si desidera passare alla funzione animata jQuery (consultare http://api.jquery.com/animate/ ). In questo modo, è possibile modificare la durata dell'animazione o eseguire una funzione di richiamata al termine dello scorrimento. Funziona solo se options.instantimpostato su false. Se è necessario disporre di un'animazione istantanea ma con un callback, impostare options.animationOptions.duration = 0invece di utilizzare options.instant = true.

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.