Как получить элемент для прокрутки в представлении, используя 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/ scrollLeftproperties на -20:

document.body.scrollLeft -= 20;
document.body.scrollTop -= 20;
Энди Э
источник
2
Спасибо! 5 других ТАК статей, и вы это прекрасно прибили. Мой вариант использования был контейнером в диалоге начальной загрузки, который нужно прокрутить в окне просмотра.
Стивен Паттен
10
Как примечание: $("#myImage")[0].scrollIntoView(false);выровняйте элемент в нижней части окна.
Филипп
1
Осторожно: «плавное» поведение широко не поддерживается и scrollIntoViewможет привести в замешательство пользователей без какой-либо анимации.
Коди Дюваль
1
@JohnHenckel: это неправильно, даже IE 5.5 имел scrollIntoViewбулевский параметр. Я постараюсь позже отправить запрос на получение caniuse.com.
Энди Э,
1
Примечание: используя Chrome, я не мог прокручивать <td>элементы в поле зрения, вместо этого пришлось прокручивать их parent ( <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 с тегом "scroll" .

Роб Стивенсон-Леггетт
источник
Я получал разные смещения / позиции в каждом браузере в моем случае, и этот плагин помог исправить это для меня! Спасибо!
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
Это работает для всех браузеров с логическим параметром или без параметров вообще. Только более продвинутый объектный параметр менее поддерживается.
Рисорд
Согласно 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
});
XEO
источник
0

Простые 2 шага для прокрутки вниз до конца или вниз.

Шаг 1: получите полную высоту прокручиваемого (разговорного) div.

Шаг 2: примените scrollTop к этому прокручиваемому элементу (диалогу), используя значение, полученное на шаге 1.

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- объект jQuery, указывающий на содержащий элемент $ target (другими словами, элемент в 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.

Dallin
источник