如何使用 jQuery 让元素滚动到视图中?

Posted

技术标签:

【中文标题】如何使用 jQuery 让元素滚动到视图中?【英文标题】:How do I get an element to scroll into view, using jQuery? 【发布时间】:2011-06-20 13:38:07 【问题描述】:

我有一个使用<ul><li><img... 的带有网格格式图像的html 文档。浏览器窗口具有垂直和水平滚动。

问题: 当我单击图像<img> 时,如何让整个文档滚动到我刚刚单击的图像为top:20px; left:20px 的位置?

我在这里浏览过类似的帖子...虽然我对 javascript 还很陌生,但我想了解自己是如何实现这一点的。

【问题讨论】:

重复:How to scroll to an element in jQuery? 【参考方案1】:

有一个名为 scrollIntoView 的 DOM 方法,所有主流浏览器都支持该方法,它将元素与视口的顶部/左侧对齐(或尽可能靠近)。

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

在支持的浏览器上,您可以提供选项:

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

或者,如果所有元素都有唯一的 ID,您只需更改 location 对象的 hash 属性即可支持后退/前进按钮:

$(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;

【讨论】:

谢谢! 5 其他 SO 文章,你完美地钉了它。我的用例是引导对话框中的一个容器,需要滚动到视图中。 注意:$("#myImage")[0].scrollIntoView(false); 将对齐窗口底部的元素。 注意:“平滑”行为并未得到广泛支持,scrollIntoView 对于没有某种动画的用户来说可能是一种令人困惑的体验。 @JohnHenckel:这是不正确的,即使 IE 5.5 也有带有布尔参数的 scrollIntoView。我稍后会尝试为 caniuse.com 发送拉取请求。 注意:使用 Chrome,我无法将 <td> 元素滚动到视图中,而是必须滚动它们的父元素 (<tr>) 并且它起作用了。【参考方案2】:

既然你想知道它是如何工作的,那我就一步步解释。

首先你要绑定一个函数作为图片的点击处理程序:

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

这会将点击处理程序应用于带有id="someImage" 的图像。如果您想对所有图像执行此操作,请将'#someImage' 替换为'img'

现在是实际的滚动代码:

    获取图像偏移量(相对于文档):

    var offset = $(this).offset(); // Contains .top and .left
    

    topleft 中减去20:

    offset.left -= 20;
    offset.top -= 20;
    

    现在为<body><html> 的scroll-top 和scroll-left CSS 属性设置动画:

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

【讨论】:

这仅适用于简单的布局。当元素嵌套在多个溢出容器中时,它并不能像 W3C .scrollIntoView 方法那样处理所有情况。 为什么要重新发明***? Element.scrollIntoView():developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView @Serge 因为它是一个尚未在所有浏览器中实现的工作草案 @JohnSmith 请仔细阅读我发布的链接,“浏览器兼容性”部分,你会看到没有浏览器不支持scrollIntoView @Serge 对不起,我没有意识到,还有 scrollIntoViewOption (这是一个不够广泛的支持)。我想这已经足够了。【参考方案3】:

我见过的最简单的解决方案

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

Tutorial Here

【讨论】:

冒着让它变得不那么简单的风险,我编辑了它以支持水平滚动。【参考方案4】:

有一些方法可以将元素直接滚动到视图中,但是如果你想滚动到一个元素的相对点,你必须手动完成:

在点击处理程序内部,获取元素相对于文档的位置,减去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));

【讨论】:

【参考方案5】:

看看jQuery.scrollTo 插件。这是demo。

这个插件有很多超出native scrollIntoView 为您提供的选项。例如,您可以将滚动设置为平滑,然后设置滚动结束时的回调。

你也可以看看all the JQuery plugins tagged with "scroll"。

【讨论】:

在我的情况下,我在每个浏览器中都获得了不同的偏移量/位置,这个插件帮助我修复了它!谢谢!【参考方案6】:

这是一个快速的 jQuery 插件,可以很好地映射内置的浏览器功能:

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

...

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

【讨论】:

【参考方案7】:

经过反复试验,我想出了这个功能,也适用于 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 );

【讨论】:

【参考方案8】:

我的 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
);

【讨论】:

我认为你需要添加:offsetthumb = $('#thumbbar-' + pageid).offset();并将对象替换为:scrollTop: offsetthumb.top - heightbar / 2 - heightthumb / 2 + offsetbar【参考方案9】:

只是一个提示。仅适用于火狐

Element.scrollIntoView();

【讨论】:

这适用于所有带有布尔参数或根本没有参数的浏览器。仅较少支持更高级的对象参数。 根据developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView,浏览器普遍缺乏对此的支持 现在只支持 Opera Mini 已经足够好了:caniuse.com/#search=scrollIntoView 有许多非常轻量级的 polyfills。【参考方案10】:

向下滚动到末尾或底部的简单 2 个步骤。

Step1:获取可滚动(对话)div的全高。

第 2 步:使用该值在该可滚动(对话)div 上应用 scrollTop 在step1中获得。

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

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

对话 div 上的每个附加都必须应用上述步骤。

【讨论】:

【参考方案11】:

在尝试找到一种可以处理各种情况的解决方案(用于为滚动设置动画的选项、在对象滚动到视图中后在对象周围填充、即使在 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 animate 函数的任何 jQuery 选项(请参阅http://api.jquery.com/animate/)。这样,您可以更改动画的持续时间或在滚动完成时执行回调函数。这仅在 options.instant 设置为 false 时有效。如果您需要即时动画但需要回调,请设置options.animationOptions.duration = 0 而不是使用options.instant = true

【讨论】:

以上是关于如何使用 jQuery 让元素滚动到视图中?的主要内容,如果未能解决你的问题,请参考以下文章

当虚拟键盘覆盖它时,如何让您的页面将输入元素滚动到视图中?

jQuery 滚动事件 - 检测元素滚动到视图中 - Chrome 上的性能不佳

如何在jquery中使滚动页脚淡入?

如何在jQuery中无限水平滚动图像?

loadNibNamed 方法太慢 - 如何让它更快?

如何让jquery动画效果在屏幕滚动到指定位置才执行