オーバーフローしたDiv内の要素にスクロールするにはどうすればよいですか?


159

div内に20のリスト項目があり、一度に5つしか表示できません。アイテム#10、次にアイテム#20にスクロールする良い方法は何ですか?すべてのアイテムの高さがわかります。

scrollToプラグインはこれを行いますが、そのソースは実際にそれに取得せずに理解することは超簡単ではありません。このプラグインを使いたくありません。

のは、私は2つの要素を取る機能を持っていないとしましょう$parentDiv$innerListItem、どちら$innerListItem.offset().top$innerListItem.positon().top私に$ parentDivの正しいscrollTopスプライトを与えます。


アップデートにより、私の回答を削除しました。しかし、この前と同じ態度を持っていた、私を信頼し、位置や余白などとブラウザの癖がたくさんあります...このプラグインは、はるかに簡単ルートと少ない時間がかかり、かつ唯一の3KであるにGZip。
Nick Craver

1
とにかくscrollToプラグインを使用します。難しいことではありません。 $("#container").scrollTo(target, duration, options)。ターゲットは単なる#anchorです。できました。
Ryan McGeary、2010

プラグインなしでこれを行うための知識があるはずです。明日はソースを読み始める
mkoryak

5
@mkoryak-知識はそこにありますが、ブラウザの癖を説明すると、基本的には... .scrollToプラグインなります。それで、なぜホイールを常に再発明するのですか?
Nick Craver

1
私見、あなたはおそらく今日あなたが.scrollToから必要とするものの正確なサブセットになるでしょう。しかし、数か月のうちに、.scrollToがIE9、FF4、およびChrome 6に更新されている間は、最初からやり直す必要があります ...これを回避するには、3kが非常に低価格のようです。
Wim

回答:


236

$innerListItem.position().top実際に相対的である.scrollTop()その最初に位置する祖先の。したがって、正しい$parentDiv.scrollTop()値を計算する方法は、それ$parentDivが配置されていることを確認することから始めることです。明示的ながまだない場合はposition、を使用しますposition: relative。要素$innerListItemとそのすべての祖先$parentDivは、明示的な位置を持つ必要はありません。これで、にスクロールできます$innerListItem

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

これは私自身のプラグインです(リストの一番上に要素を配置します。特にのために使用しoverflow-y : autoます。overflow-x!では動作しない可能性があります):

elemページのスクロール先となる要素のHTMLセレクタです。:などのjQueryによってサポート何か、#myiddiv.myclass$(jquery object)、[DOMオブジェクト]、等

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

アニメーション化する必要がない場合は、次を使用します。

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

使い方:

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

注:#innerItemはどこにでも置くことができます#overflow_div。直接の子である必要はありません。

Firefox(23)およびChrome(28)でテスト済み。

ページ全体をスクロールする場合は、この質問を確認してください。


elemですか?あなたはそれをまったく説明しません。
vsync 2014年

代わりにfn.scrollToの$をjQueryにスワップすると、マイレージ/競合が改善されます
Barry

このビッグ欠陥、あなたがスコープを含まない:$(this).scrollTop($(this).scrollTop() - $(this).offset().top + $(elem, $(this)).offset().top);-について
ルークスノーデン

1
ページと要素の間に上マージンを残したい場合(場合によっては見栄えがよくなる場合があります)、たとえば10pxを引きます$(this).scrollTop() - $(this).offset().top + $(elem).offset().top - 10
lepe 2016年

FirefoxとChrome(またはその他のブラウザ)の位置に違いがある場合は、htmlコードを確認してください(このバグレポートを参照)
lepe

34

Glenn Mossの回答を調整して、オーバーフローdivがページの上部にない場合があることを考慮しました。

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

私はこれを、レスポンシブテンプレートを備えたGoogleマップアプリケーションで使用していました。解像度> 800pxでは、リストはマップの左側にありました。解像度<800では、リストはマップの下にありました。


6

上記の回答は、overflow要素内に表示されている場合でも、over要素の上部に内部要素を配置します。私はそれを望まなかったので、要素が表示されている場合にスクロール位置を変更しないように変更しました。

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

これは私を助けました!! 参照してくださいstackoverflow.com/questions/48283932/...
遺伝子bを。

1

私はこれら2つの関数を記述して、私の人生を楽にしています。

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

そしてそれらを使用してください:

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

elem.offset().top画面の上から計算しています。親要素から計算してほしい。それ、どうやったら出来るの ?
サントッシュ

0

それを非常に長い間遊んだ後、これは私が思いついたものです:

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

そして私はそれをこのように呼びます

$("#basketListGridHolder").scrollTo('tr[data-uid="' + basketID + '"]');
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.