Як я можу отримати елемент для прокрутки до перегляду за допомогою 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. Віднімаємо 20 від topі 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, оскільки це робочий проект, який реалізований не у всіх браузерах
Джон Сміт,

@JohnSmith, будь ласка, прочитайте уважно посилання, яке я опублікував, розділ "Сумісність браузера", ви побачите, що браузер не підтримуєscrollIntoView
Сергій,

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

377

Існує метод DOM, який називається scrollIntoView, який підтримується всіма основними браузерами, який вирівняє елемент у верхній / лівій частині вікна перегляду (або як можна ближче).

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

У підтримуваних браузерах ви можете надати варіанти:

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

Крім того, якщо всі елементи мають унікальні ідентифікатори, ви можете просто змінити 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, і ти їх чудово прибив. Моїм випадком використання був контейнер у діалоговому вікні завантаження, який потрібно прокрутити до перегляду.
Стівен Паттен

10
Як зауваження: $("#myImage")[0].scrollIntoView(false);вирівняйте елемент у нижній частині вікна.
Філіп

1
Остерігайтеся: "плавне" поведінка не підтримується широко, і scrollIntoViewможе бути заплутаним для користувачів без будь-якої анімації.
Коді Дюваль

1
@JohnHenckel: це неправильно, навіть IE 5.5 мав scrollIntoViewбулевий параметр. Я спробую пізніше надіслати запит на пошук на caniuse.com.
Енді Е

1
Примітка. Використовуючи Chrome, я не зміг прокрутити <td>елементи до перегляду, натомість довелося прокручувати їх батьківський ( <tr>), і це спрацювало.
CrazyTim

13

Найпростіше рішення, яке я бачив

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

Підручник Тут


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

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 . Наприклад, ви можете встановити прокрутку як плавну, а потім встановити зворотний дзвінок, коли прокрутка закінчиться.

Ви також можете переглянути всі плагіни 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
Джон Магнолія

Для цього є ряд дуже легких поліфілів.
Мартін Джеймс

1

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

розмітка:

<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. Отримайте повний зріст ділового прокрутки (бесіди).

Крок 2: застосуйте scrollTop до цього поділу для прокрутки (бесіди), використовуючи значення, отримане на кроці 1.

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

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

Вище описані кроки повинні бути застосовані до кожного додатка до розділу розмови.


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- об’єкт jQuery, що вказує на містить елемент $ target (іншими словами, елемент у домі зі смугами прокрутки). За замовчуванням використовується вікно, яке містить цільовий елемент $ і досить розумне, щоб вибрати вікно iframe. Не забудьте додати $ у назві властивості.

options.padding- прокладки в пікселях, які потрібно додати над об'єктом або під ним, коли він прокручується до перегляду. Таким чином, це не вірно до краю вікна. За замовчуванням до 20.

options.instant- якщо встановлено значення true, анімація jQuery не використовуватиметься, а прокрутка миттєво з’явиться у потрібному місці. Типово встановлено значення false.

options.animationOptions- будь-які варіанти jQuery, які ви хочете перейти до функції анімації jQuery (див. http://api.jquery.com/animate/ ). За допомогою цього ви можете змінити тривалість анімації або виконати функцію зворотного дзвінка, виконану після завершення прокрутки. Це працює лише якщо options.instantвстановлено значення false. Якщо вам потрібна миттєва анімація, але з зворотним дзвінком, встановіть options.animationOptions.duration = 0замість цього options.instant = true.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.