仅在不在视图中时滚动到元素 - jQuery

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了仅在不在视图中时滚动到元素 - jQuery相关的知识,希望对你有一定的参考价值。

我知道有几次这样的变化;我已经浏览了一段时间,但要么我做错了,要么我找不到我需要的东西。

我有一个嵌套注释的结构,几乎和Facebook Comments plugin一样,每当点击reply时,一个带有textarea的小表单和一个按钮出现在注释的底部。

同样,行为与Facebook Comments plugin相同,我想在滚动新添加textarea到视图时实现相同的目标。

我已经尝试了scrollTo插件,它工作顺利但是,即使我手动滚动到页面的最底部,滚动动画将始终重置滚动位置并从顶部开始。

为了记录,这就是我调用scrollTo的方式:

$.scrollTo($('#addReply_1'), 800);

其中addReply_1是包含该形式的div。我已经大步滚动到表单本身和textarea。结果相同。

有没有办法滚动到元素只有它尚未可见?

我已经尝试过很多解决方案,就像Scroll to an element using jQuery一样,但似乎没有任何表现符合要求;甚至Scroll to a particular element w/ jQueryCheck if element is visible after scrolling也表现出相同的“跳跃”行为。


更新:在线演示以显示行为

我上传了一个html演示页面,显示了我抱怨的行为:http://www.wouldbebetter.com/demo/comment-demo.htm

只需滚动到页面底部,然后单击任何Reply链接即可查看我所指的“跳跃”滚动。

请注意,此演示使用@Robert Koritnik的答案的scrollintoview插件,但如果我使用ScrollTo,则行为是相同的。

答案

是的,只有当jQuery插件不在可滚动祖先的可见边界内时,它才会滚动到元素。我写过一个完全符合你的要求。与scrollTo()相比,您可能会发现它更容易使用,因为您只需要提供您想要看到的元素。

我可以在这里复制粘贴代码,但由于我不时添加一些附加内容,最好将您链接到blog post,在那里您将找到与编程滚动和最新插件代码相关的所有细节。程序化滚动可能会让用户和整个用户界面体验分散注意力,因此我认为这将是一个有趣的阅读。

用法

插件非常简单易用:

$("#ElementToScrollIntoView").scrollintoview();

插件会自动找到最近的可滚动祖先并相应地滚动它(如果需要的话)。您可以使用此插件的一些其他设置,这就是它们的样子:

scrollintoview: function (options) 
    /// <summary>Scrolls the first element in the set into view by scrolling its closest scrollable parent.</summary>
    /// <param name="options" type="Object">Additional options that can configure scrolling:
    ///        duration (default: "fast") - jQuery animation speed (can be a duration string or number of milliseconds)
    ///        direction (default: "both") - select possible scrollings ("vertical" or "y", "horizontal" or "x", "both")
    ///        complete (default: none) - a function to call when scrolling completes (called in context of the DOM element being scrolled)
    /// </param>
    /// <return type="jQuery">Returns the same jQuery set that this function was run on.</return>

我在我的Sharepoint 2010网站上使用这个插件,在我提供长表格数据的页面上。每当我向这个表添加一个新项目(行)时,我还会滚动到这个新记录并突出显示它,这样用户就可以立即看到新记录。

Sharepoint也是我决定不手动提供可滚动元素而是以编程方式查找它的原因。 Sharepoint使用admin costumizable主页,这意味着我不知道哪个元素在运行时可以滚动。但我确实知道我想看哪个元素。因此这个插件。与支持各种不同场景的scrollTo()插件相比,它也相当简化。大多数时候,开发人员倾向于只使用一个(或者数量非常有限)。

补充意见

默认链接点击处理预防

使用我的插件仍然会使它成为问题,因为添加这些回复框时会有一些闪烁。问题是您的链接点击实际执行。您应该阻止这种情况,以使您的页面顺利运行:

  1. 或者通过以下两种方式之一在链接上设置点击事件: <a href="javascript:void AddReplyForm(44); return false;">Reply</a> 要么 <a href="#" onclick="void AddReplyForm(44); return false;">Reply</a>
  2. 更好的方法是在文档就绪上运行: $(function() $("a").click(function(evt) evt.preventDefault(); ); );

主要思想是阻止浏览器处理链接点击。因为这会使浏览器查找页内锚点,因为它找不到,所以它会自动滚动到顶部。然后你告诉它滚动到你的元素。

重复的ID

创建回复表单时,添加新元素和新元素,但它们都具有相同的ID。您应该避免这样做或使用其他方法。您可以通过向BindClick()函数提供元素来完全删除ID。主回复生成函数也可以看起来像这样(这个函数的编写方式完全消除了元素ID的需要):

function AddReplyForm(topCommentID)

    var el = $(addReplyForm).appendTo('#comment_' + topCommentID + ' .right');
    BindClick(el); // mind this !! you provide the element to remove
    el.scrollintoview();

另一答案

有同样的问题......在回顾几个答案之后,这就是我想出来做的事情......没有拉下另一个插件。

function scrollIntoViewIfNeeded($target) 
    if ($target.position()) 
        if ($target.position().top < jQuery(window).scrollTop())
            //scroll up
            $('html,body').animate(scrollTop: $target.position().top);
        
        else if ($target.position().top + $target.height() >
            $(window).scrollTop() + (
                window.innerHeight || document.documentElement.clientHeight
            )) 
            //scroll down
            $('html,body').animate(scrollTop: $target.position().top -
                (window.innerHeight || document.documentElement.clientHeight)
                    + $target.height() + 15
            );
        
    

最后一行的“15”只是额外填充 - 您可能需要调整它,或将其添加到向上滚动行。

编辑:将window.innerHeight更改为(window.innerHeight || document.documentElement.clientHeight),IE <8支持

另一答案

所有现代浏览器都支持这一点。访问:http://caniuse.com/#search=scrollIntoView

function scrollIntoViewIfNeeded(target) 
    var rect = target.getBoundingClientRect();
    if (rect.bottom > window.innerHeight) 
        target.scrollIntoView(false);
    
    if (rect.top < 0) 
        target.scrollIntoView();
     

更新

目标必须是元素。如果你使用jQuery调用这样的函数:

scrollIntoViewIfNeeded($(".target")[0]);
另一答案

确保元素在容器内的视图中:

let rectElem = elem.getBoundingClientRect(), rectContainer=container.getBoundingClientRect();
if (rectElem.bottom > rectContainer.bottom) elem.scrollIntoView(false);
if (rectElem.top < rectContainer.top) elem.scrollIntoView();
另一答案

我稍微修改了@iandisme的答案并将其作为一个小的jquery插件包装起来:

(function ($) 
'use strict';

$.fn.scrollToSimple = function ($target) 
    var $container = this.first();      // Only scrolls the first matched container

    var pos = $target.position(), height = $target.outerHeight();
    var containerScrollTop = $container.scrollTop(), containerHeight = $container.height();
    var top = pos.top + containerScrollTop;     // position.top is relative to the scrollTop of the containing element

    var paddingPx = containerHeight * 0.15;      // padding keeps the target from being butted up against the top / bottom of the container after scroll

    if (top < containerScrollTop)      // scroll up                
        $container.scrollTop(top - paddingPx);
    
    else if (top + height > containerScrollTop + containerHeight)      // scroll down
        $container.scrollTop(top + height - containerHeight + paddingPx);
    
;
)(jQuery);

我删除了对.animate的调用,因为我正在寻找即时滚动。我还添加了滚动任何(可滚动)容器的功能,而不仅仅是窗口。用法示例:

// scroll the window so #target  is visible
$(window).scrollToSimple( $("#target") );

// scroll the scrollable element #container so that #target is visible
$("#container").scrollToSimple( $("#target") );
另一答案

我不知道我是否理解你想要的东西,但看看是不是这样,接近或者如果我完全迷失了:

<!DOCTYPE html>
<html>
    <head>
        <title>Scroll To Reply</title>
        <meta charset="utf-8" />
     <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
        <script type="text/javascript">
            $(document).ready(function()
                var $contextarea = $('#contextform textarea');
                $('a.reply').live('click',function()
                    $(this).closest('p').css('margin-top':'300px;');
                    $('#contextform').appendTo($(this).closest('p'));
                    $('#contextform').slideDown(1000);//.css('display':'block');
                    $(this).closest('p').attr('id','scrolltome');
                    $('html,body').animate(slideDown: $('#scrolltome').offset().top, 2000);
                );
                $('.sendreply').live('click',function()
                    if($contextarea.val() == null || $contextarea.val() == '') 
                        alert('textarea is empty!');
                     else 
                        $('#contextform').slideUp(800);
                    
                );

                //                $('button').click(function() 
                //                    $('html,body').animate(scrollTop: $('#body').offset().top, 2000);//scrolls to the top
                //                );

            );
        </script>
        <style type="text/css">
            body
                font-size:25px;
                font-family: 'Arimo', Arial, sans-serif;
            
            #contextform 
                display:none;
                width:500px;
                height: 150px;
                background: #0489B7;
                padding: 5px
            
            #contextform textarea 
                width: 490px;
                height: 90px;
            
        </style>
    </head>
    <body id="body">
        <h1>Scroll to reply</h1&g

以上是关于仅在不在视图中时滚动到元素 - jQuery的主要内容,如果未能解决你的问题,请参考以下文章

当内容滚动到视图中时激活 CSS3 动画

google不在视图范围内需要滚动

元素在视口中时的jquery触发功能

ScrollViewer - 指示子元素滚动到视图中

JQuery:当元素在视图中时触发动作

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