Як прокрутити елемент до переповненого Div?


159

У мене є 20 елементів списку всередині div, які можуть показувати лише 5 за один раз. Який хороший спосіб перейти до пункту №10, а потім до пункту №20? Я знаю висоту всіх предметів.

scrollToПлагін робить це, але його джерело не дуже легко зрозуміти , на самому ділі не потрапити в нього. Я не хочу використовувати цей плагін.

Скажімо , у мене є функція , яка приймає 2 елементи $parentDiv, $innerListItemні $innerListItem.offset().topні $innerListItem.positon().topдає мені правильний scrollTop за $ parentDiv.


Мою відповідь видалено через ваше оновлення. Але повірте мені, маючи таке ж ставлення і раніше, є багато химерностей браузера з положенням і полями тощо ... плагін набагато простіший маршрут і менш трудомісткий, і лише 3 к перед GZip.
Нік Крейвер

1
Користуйтеся плагіном scrollTo в будь-якому випадку. Це не складно. $("#container").scrollTo(target, duration, options). Ціль - це лише ан #anchor. Зроблено.
Райан Макгірі

здається, що там повинні бути знання, щоб це зробити без плагіна. завтра погано почне читати джерело
mkoryak

5
@mkoryak - Знання існують там, але коли ви записуєтесь на химерність браузера, ви, в основному, закінчуєтесь ... плагіном .scrollTo , то чому навіщо весь час винаходити колесо?
Нік Крейвер

1
ІМХО, ви, ймовірно, закінчитеся з точним набором того, що вам потрібно .scrollДо сьогодні . Але через кілька місяців, поки .scrollTo було оновлено до IE9, FF4 та Chrome 6, вам доведеться почати заново ... 3k здається дуже низькою ціною, щоб уникнути цього.
Вім

Відповіді:


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, як: #myid, div.myclass, $(jquery object), [будинок об'єкт], і т.д.

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

Ви пройдете кращий пробіг / безконфліктність, якщо поміняєте $ на fn.scrollДля того, щоб замість jQuery
Barry Carlyon

Великий недолік у цьому, ваш не містить рамки: $(this).scrollTop($(this).scrollTop() - $(this).offset().top + $(elem, $(this)).offset().top);- З повагою
Люк Сноуден

1
Якщо ви хочете залишити деякий верхня межа між сторінкою та елементом (який може виглядати краще в деяких випадках), віднімати, наприклад, 10px, як: $(this).scrollTop() - $(this).offset().top + $(elem).offset().top - 10.
лепе

Якщо у вас є різниці в положенні між Firefox та Chrome (або іншими браузерами), перевірте свій html-код (див. Цей звіт про помилку )
lepe

34

Я відкоригував відповідь Гленна Мосса, щоб врахувати той факт, що переповнення діва може бути не вгорі сторінки.

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

Я використовував це в додатку Google Maps з чуйним шаблоном. Роздільна здатність> 800 пікселів, список знаходився в лівій частині карти. За роздільною здатністю <800 список був нижче карти.


6

Вищенаведені відповіді будуть розташовувати внутрішній елемент у верхній частині елемента, що переливається, навіть якщо він видно всередині елемента, що переливається. Я цього не хотів, тому я змінив його, щоб не змінювати положення прокрутки, якщо елемент переглядається.

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 + '"]');
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.