Wie kann ich mithilfe von jQuery ein Element in die Ansicht scrollen?

169

Ich habe ein HTML-Dokument mit Bildern in einem Rasterformat mit <ul><li><img.... Das Browserfenster bietet sowohl vertikales als auch horizontales Scrollen.

Frage: Wenn ich auf ein Bild klicke <img>, wie kann ich dann das gesamte Dokument zu einer Position scrollen, an der sich das Bild befindet, auf das ich gerade geklickt habe top:20px; left:20px?

Ich habe hier nach ähnlichen Beiträgen gesucht ... obwohl ich noch ziemlich neu in JavaScript bin und verstehen möchte, wie dies für mich selbst erreicht wird.

Nasir
quelle

Antworten:

192

Da Sie wissen möchten, wie es funktioniert, erkläre ich es Schritt für Schritt.

Zuerst möchten Sie eine Funktion als Klick-Handler des Bildes binden:

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

Dadurch wird der Klick-Handler auf ein Bild mit angewendet id="someImage". Wenn Sie dies für alle Bilder tun möchten , ersetzen Sie '#someImage'durch 'img'.

Nun zum eigentlichen Bildlaufcode:

  1. Holen Sie sich die Bildversätze (relativ zum Dokument):

    var offset = $(this).offset(); // Contains .top and .left
  2. Subtrahiere 20 von topund left:

    offset.left -= 20;
    offset.top -= 20;
  3. Animieren Sie nun die CSS-Eigenschaften von <body>und nach oben und links <html>:

    $('html, body').animate({
        scrollTop: offset.top,
        scrollLeft: offset.left
    });
David Tang
quelle
3
Dies funktioniert nur bei einfachen Layouts. Es behandelt nicht alle Fälle wie die W3C- .scrollIntoViewMethode, wenn Elemente in mehreren überlaufenden Containern verschachtelt sind.
Natevw
2
Warum das Rad neu erfinden? Element.scrollIntoView(): developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
Serge
@ Serge, weil es ein funktionierender Entwurf ist, der nicht in allen Browsern implementiert wurde
John Smith
@ JohnSmith Bitte lesen Sie aufmerksam den Link, den ich gepostet habe, den Abschnitt "Browserkompatibilität". Sie werden sehen, dass es keinen Browser gibt, der das nicht unterstütztscrollIntoView
Serge
@Serge Entschuldigung, ich wusste nicht, dass es auch scrollIntoViewOption gibt (die nicht breit genug unterstützt wird). Ich denke es ist gut genug.
John Smith
377

Es gibt eine DOM-Methode namens scrollIntoView, die von allen gängigen Browsern unterstützt wird und die ein Element am oberen / linken Rand des Ansichtsfensters ausrichtet (oder so nah wie möglich).

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

In unterstützten Browsern können Sie folgende Optionen bereitstellen:

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

Wenn alle Elemente eindeutige IDs haben, können Sie alternativ einfach die hashEigenschaft des locationObjekts für die Unterstützung von Schaltflächen für Zurück / Vorwärts ändern :

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

Passen Sie danach einfach die scrollTop/ scrollLeft-Eigenschaften um -20 an:

document.body.scrollLeft -= 20;
document.body.scrollTop -= 20;
Andy E.
quelle
2
Danke dir! 5 andere SO-Artikel und du hast es perfekt genagelt. Mein Anwendungsfall war ein Container in einem Bootstrap-Dialogfeld, der in die Ansicht scrollen muss.
Stephen Patten
10
Hinweis: $("#myImage")[0].scrollIntoView(false);Richtet das Element am unteren Rand des Fensters aus.
Philipp
1
Achtung: Das "reibungslose" Verhalten wird nicht allgemein unterstützt und scrollIntoViewkann für Benutzer ohne irgendeine Art von Animation eine verwirrende Erfahrung sein.
Cody Duval
1
@ JohnHenckel: Das ist falsch, sogar IE 5.5 hatte scrollIntoViewmit dem booleschen Parameter. Ich werde später versuchen, eine Pull-Anfrage für caniuse.com zu senden.
Andy E
1
Hinweis: Mit Chrome konnte ich keine <td>Elemente in die Ansicht scrollen , sondern musste deren übergeordnetes Element ( <tr>) scrollen, und es funktionierte.
CrazyTim
13

Einfachste Lösung, die ich gesehen habe

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

Tutorial hier

Matt Watson
quelle
Auf die Gefahr hin, es weniger einfach zu machen, habe ich dies bearbeitet, um auch das horizontale Scrollen zu unterstützen.
Jpaugh
7

Es gibt Methoden, um Elemente direkt in die Ansicht zu scrollen. Wenn Sie jedoch zu einem Punkt relativ zu einem Element scrollen möchten, müssen Sie dies manuell tun:

Ermitteln Sie im Click-Handler die Position des Elements relativ zum Dokument, subtrahieren Sie 20und verwenden Sie 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
quelle
7

Schauen Sie sich das Plugin jQuery.scrollTo an . Hier ist eine Demo .

Dieses Plugin bietet viele Optionen, die über das native scrollIntoView hinausgehen Ihnen bietet. Sie können beispielsweise das Scrollen so einstellen, dass es flüssig ist, und dann einen Rückruf festlegen, wenn das Scrollen beendet ist.

Sie können sich auch alle mit "scroll" gekennzeichneten JQuery-Plugins ansehen .

Rob Stevenson-Leggett
quelle
Ich habe in meinem Browser in jedem Browser unterschiedliche Offsets / Positionen erhalten, und dieses Plugin hat mir dabei geholfen, das Problem zu beheben! Vielen Dank!
LaurelB
4

Hier ist ein schnelles jQuery-Plugin, mit dem Sie die integrierten Browserfunktionen gut abbilden können:

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

...

$('.my-elements').ensureVisible();
rauben
quelle
3

Nach Versuch und Irrtum habe ich mir diese Funktion ausgedacht, funktioniert auch mit 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 });
}
Ton Škoda
quelle
2

Nur ein Tipp. Funktioniert nur mit Firefox

Element.scrollIntoView ();

wp Student
quelle
4
Dies funktioniert für alle Browser mit booleschen Parametern oder ohne Parameter. Nur erweiterte Objektparameter werden weniger unterstützt.
Risord
Laut developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView gibt es generell einen Mangel an Browserunterstützung dafür
lfender6445
Es wird jetzt gut genug unterstützt, nur Opera Mini: caniuse.com/#search=scrollIntoView
John Magnolia
Es gibt eine Reihe sehr leichter Polyfills dafür.
Martin James
1

Meine Benutzeroberfläche verfügt über eine vertikale Liste von Daumen in einer Daumenleiste. Ziel war es, den aktuellen Daumen genau in der Mitte der Daumenleiste zu platzieren. Ich ging von der genehmigten Antwort aus, stellte jedoch fest, dass es einige Verbesserungen gab, um den aktuellen Daumen wirklich zu zentrieren. hoffe, das hilft jemand anderem.

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
quelle
0

Einfache 2 Schritte zum Scrollen nach unten bis zum Ende oder unten.

Schritt 1: Holen Sie sich die volle Höhe von scrollbaren (Konversations-) Div.

Schritt 2: Wenden Sie scrollTop mit dem in Schritt 1 erhaltenen Wert auf dieses scrollbare (Konversations-) Div an.

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

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

Die obigen Schritte müssen für jeden Anhang im Konversationsbereich angewendet werden.

Shiva Kumar P.
quelle
0

Nachdem ich versucht hatte, eine Lösung zu finden, die alle Umstände bewältigte (Optionen zum Animieren der Schriftrolle, Auffüllen des Objekts, sobald es in die Ansicht gescrollt wurde, funktioniert auch unter dunklen Umständen wie in einem Iframe), schrieb ich schließlich meine eigene Lösung dafür. Da es zu funktionieren scheint, wenn viele andere Lösungen fehlgeschlagen sind, dachte ich, ich würde es teilen:

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 ist ein jQuery-Objekt, das das Objekt enthält, in das Sie bei Bedarf scrollen möchten.

options (optional) kann die folgenden in einem Objekt übergebenen Optionen enthalten:

options.$container- Ein jQuery-Objekt, das auf das enthaltende Element von $ target zeigt (dh das Element im Dom mit den Bildlaufleisten). Der Standardwert ist das Fenster, das das $ target-Element enthält und intelligent genug ist, um ein Iframe-Fenster auszuwählen. Denken Sie daran, das $ in den Eigenschaftsnamen aufzunehmen.

options.padding- das Auffüllen in Pixel, das über oder unter dem Objekt hinzugefügt werden soll, wenn es in die Ansicht gescrollt wird. Auf diese Weise ist es nicht direkt am Rand des Fensters. Der Standardwert ist 20.

options.instant- Wenn true festgelegt ist, wird jQuery animate nicht verwendet und der Bildlauf wird sofort an die richtige Stelle verschoben. Der Standardwert ist false.

options.animationOptions- Alle jQuery-Optionen, die Sie an die jQuery-Animationsfunktion übergeben möchten (siehe http://api.jquery.com/animate/ ). Mit dieser Option können Sie die Dauer der Animation ändern oder eine Rückruffunktion ausführen lassen, wenn der Bildlauf abgeschlossen ist. Dies funktioniert nur, wenn options.instantfalse festgelegt ist. Wenn Sie eine sofortige Animation mit einem Rückruf benötigen, stellen Sie diese options.animationOptions.duration = 0anstelle der Verwendung ein options.instant = true.

dallin
quelle