jQueryを使用して、要素をスクロールして表示する方法を教えてください。


169

を使用してグリッド形式の画像を含むHTMLドキュメントがあります<ul><li><img...。ブラウザウィンドウには、垂直スクロールと水平スクロールの両方があります。

質問: 画像をクリックしたときに、クリックした<img>ばかりの画像がある位置までドキュメント全体をスクロールするにはどうすればよいtop:20px; left:20pxですか?

私はここで同様の投稿を閲覧しました...ただし、JavaScriptは非常に新しいので、これが自分でどのように実現されるのかを理解したいと思っています。


回答:


192

どのように機能するかを知りたいので、順を追って説明します。

まず、画像のクリックハンドラーとして関数をバインドします。

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

これにより、クリックハンドラーが画像に適用されますid="someImage"。あなたがこれをしたい場合は、すべての画像、交換してください'#someImage''img'

次に、実際のスクロールコードについて説明します。

  1. (ドキュメントに対する)画像のオフセットを取得します。

    var offset = $(this).offset(); // Contains .top and .left
  2. topおよびから20を減算しleftます。

    offset.left -= 20;
    offset.top -= 20;
    
  3. 今のスクロールトップとスクロール左のCSSプロパティをアニメーション<body><html>

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

3
これは単純なレイアウトでのみ機能します。.scrollIntoView要素が複数のオーバーフローコンテナ内にネストされている場合、W3C メソッドのようにすべてのケースを処理するわけではありません。
natevw

2
なぜ車輪を再発明するのですか?Element.scrollIntoView()developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
Serge

@Sergeは、すべてのブラウザに実装されていない草案であるため
John Smith

@JohnSmithは、私が投稿したリンクの「ブラウザーの互換性」セクションを注意深く読んでください。ブラウザーがサポートされていないことがわかりますscrollIntoView
Serge

@Serge申し訳ありませんが、気付かなかったのですが、scrollIntoViewOption(十分に広くサポートされていないオプション)もありました。それで十分だと思います。
John Smith、

377

と呼ばれるDOMメソッドがありますscrollIntoView。これは、すべての主要なブラウザーでサポートされており、要素をビューポートの上/左(または可能な限り近く)に配置します。

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

サポートされているブラウザでは、オプションを提供できます。

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

または、すべての要素に一意のIDがある場合hashは、locationオブジェクトのプロパティを変更して、戻る/進むボタンをサポートできます。

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

その後、scrollTop/ scrollLeftプロパティを-20 だけ調整します。

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

2
ありがとうございました!他の5つのSO記事とあなたはそれを完璧に釘付けにしました。私の使用例は、スクロールして表示する必要のあるブートストラップダイアログのコンテナーでした。
スティーブンパッテン2013年

10
注:$("#myImage")[0].scrollIntoView(false);要素をウィンドウの下部に配置します。
フィリップ14

1
注意:「滑らかな」動作は広くサポートされておらscrollIntoViewず、何らかのアニメーションを持たないユーザーにとって混乱を招く可能性があります。
Cody Duval

1
@JohnHenckel:不正解です。IE5.5でもscrollIntoViewbooleanパラメータがありました。caniuse.comのプルリクエストは後で送信します。
Andy E

1
注:Chromeを使用して<td>要素を表示することができず、代わりに親(<tr>)をスクロールする必要があり、機能しました。
CrazyTim


7

要素を直接ビューにスクロールする方法がありますが、要素から相対的なポイントまでスクロールする場合は、手動で行う必要があります。

クリックハンドラー内で、ドキュメントに対する要素の位置を取得し、減算20して使用します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

jQuery.scrollToプラグインを見てください。こちらがデモです。

このプラグインには、ネイティブのscrollIntoViewが提供するものを超える多くのオプションがあります。たとえば、スクロールがスムーズになるように設定し、スクロールが終了したときのコールバックを設定できます。

"scroll"でタグ付けされたすべてのJQueryプラグインを確認することもできます


私の場合、すべてのブラウザで異なるオフセット/位置を取得していましたが、このプラグインはそれを修正するのに役立ちました!ありがとう!
LaurelB

4

組み込みのブラウザ機能を適切にマッピングするための簡単なjQueryプラグインを次に示します。

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

...

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

3

試行錯誤の末、私はこの機能を思いつきましたが、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

ほんのヒント。Firefoxでのみ動作します

Element.scrollIntoView();


4
これは、ブールパラメータを使用するか、パラメータをまったく使用しないすべてのブラウザで機能します。より高度なオブジェクトパラメータのみがサポートされています。
Risord

developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewによると、これに対するブラウザーサポートの一般的な欠如があります
lfender6445

Opera Miniのみで十分サポートされています:caniuse.com/#search=scrollIntoView
John Magnolia

非常に軽量なポリフィルがたくさんあります。
マーティンジェームズ

1

私のUIには、サムバー内のサムの垂直スクロールリストがあります。目標は、現在のサムをサムバーの中央に配置することでした。私は承認された回答から始めましたが、現在の親指を真に中央に合わせるための微調整がいくつかあることがわかりました。これが他の誰かを助けることを願っています。

マークアップ:

<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

最後または最後までスクロールするための簡単な2つのステップ。

ステップ1:スクロール可能な(会話)divの高さ全体を取得します。

ステップ2:ステップ1で取得した値を使用して、そのscrollable(conversation)divにscrollTopを適用します。

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

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

上記の手順は、会話divのすべての追加に適用する必要があります。


0

すべての状況を処理するソリューション(スクロールをアニメーション化するオプション、オブジェクトがスクロールして表示されるとオブジェクトの周囲をパディングするオプション、iframeなどのあいまいな状況でも機能する)を見つけた後、最終的にこれに独自のソリューションを記述しました。他の多くの解決策が失敗したときに機能するように見えるので、私はそれを共有したいと思いました:

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 必要に応じてスクロールして表示したいオブジェクトを含むjQueryオブジェクトです。

options (オプション)オブジェクトに渡される次のオプションを含めることができます。

options.$container-$ targetを含む要素を指すjQueryオブジェクト(つまり、スクロールバーを備えたdom内の要素)。デフォルトは、$ target要素を含み、iframeウィンドウを選択するのに十分スマートなウィンドウです。プロパティ名に$を含めることを忘れないでください。

options.padding-オブジェクトがスクロールされて表示されるときに、オブジェクトの上または下に追加するピクセル単位のパディング。この方法では、ウィンドウの端に対して正しくありません。デフォルトは20です。

options.instant-trueに設定すると、jQuery animateは使用されず、スクロールがすぐに正しい場所に表示されます。デフォルトはfalseです。

options.animationOptions-jQueryアニメーション関数に渡したいjQueryオプション(http://api.jquery.com/animate/を参照)。これにより、アニメーションの継続時間を変更したり、スクロールが完了したときにコールバック関数を実行したりできます。これoptions.instantは、がfalseに設定されている場合にのみ機能します。インスタントアニメーションが必要だがコールバックがある場合は、options.animationOptions.duration = 0を使用する代わりにを設定しoptions.instant = trueます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.