代码之家  ›  专栏  ›  技术社区  ›  Daddy Warbox

jquery建议:如何改进将元素滚动到视图中的函数?

  •  1
  • Daddy Warbox  · 技术社区  · 15 年前

    我创建了一个函数,它将给定的子元素滚动到其父元素内的视图中。具体如下:

    function keepScrolledOver( elem )
    {
        frame = elem.parent();
    
        var scrollPos = frame.scrollTop();
        var offset = elem.attr( "offsetTop" );
    
        // If the element is scrolled too high...
        if( offset < scrollPos )
        {
            frame.scrollTop( offset );
            // frame.attr( "scrollTop", offset );
        }
    
        // If the element is scrolled too low...
        else
        {
            var frameHeight = frame.height();
            var offsetBottom = offset + elem.height();
            var scrollBottom = scrollPos + frameHeight;
    
    
            if( offsetBottom > scrollBottom )
            {
                // frame.attr( "scrollTop", offsetBottom );
                if( frameHeight < offsetBottom )
                    frame.scrollTop( offsetBottom - frameHeight );
                    // frame.attr( "scrollTop", offsetBottom - frameHeight );
            }
        }
    }
    

    到目前为止,对于我的火狐网络应用程序(火狐是我迄今为止测试过的所有应用程序),这非常有效。唯一的问题是,对于滚动得太低的元素,它总是倾向于滚动到目标元素的前面一点点,而不是一直滚动到它的末尾。我不确定元素填充是否与我的数学有关,或者我的数学不好。

    有人对如何改进这个有什么高见吗?

    1 回复  |  直到 15 年前
        1
  •  1
  •   Van Miranda    15 年前

    如果元素太高,则激发的代码部分可以很好地工作,假定框架元素及其子元素处于相对位置。如果没有,则使用绝对偏移量,但不起作用。

    至于在元素太低的情况下激发的部分,我假设当您说“它总是倾向于滚动到目标元素的前面一点点,而不是一直滚动到它的末尾”时,您指的是如果帧小于它的偏移量,元素就会被切断。尝试以下操作:

    // If the frame is less than or equal to the element's height
    if( frameHeight <= elem.attr('height') ){
       //Scroll to it's offsetBottom - the total frameHeight, so that the full element will be displayed
       frame.scrollTop( offsetBottom - frameHeight ); 
    }else {
       //Else, the element's height is less than the frame, so the entire element will be displayed if we just scroll to the element's offsetBottom.
       frame.scrollTop( offsetBottom );
    }
    

    我创建了一个HTML演示页面,如下所示,没有遇到任何其他问题。玩转各种元素的高度,看看你能不能让它打破。我使用了火狐3.5,一切都很酷。

        <button id="buttonTest1">Slide to Test1</button> <button id="buttonTest2">Slide to Test2</button>
    <div style="position:relative;width:100%;height:620px;overflow:scroll;">
        <div style="position:relative;height:50px;"></div>
        <div id="childSlide1" style="width:50px;height:50px;position:relative;">Test</div>
        <div id="childSlide2" style="width:50px;height:50px;position:relative;top:850px;">Test2</div>
    </div>
    
    
    $(document).ready(function(){
        function keepScrolledOver( elem ){
            var frame = elem.parent();
    
            var scrollPos = frame.scrollTop();
            var offset = elem.attr( "offsetTop" );
            alert ('scrollPos: '+scrollPos+' offset: '+offset);
            //var jQoffset = elem.offset();
            //alert ('jQoffset: '+jQoffset.top+' '+jQoffset.left);
            // If the element is scrolled too high...
            if( offset < scrollPos )
            {
                    alert ('scrollPos '+scrollPos+' is bigger than offset '+offset);
                    frame.scrollTop( offset );
                    // frame.attr( "scrollTop", offset );
            }
    
            // If the element is scrolled too low...
            else
            {
                    var frameHeight = frame.height();
                    var offsetBottom = offset + elem.height();
                    var scrollBottom = scrollPos + frameHeight;
                    alert('frameHeight: '+frameHeight+' offsetBottom: '+offsetBottom+' scrollBottom: '+scrollBottom);
    
    
                    if( offsetBottom > scrollBottom )
                    {
                            // frame.attr( "scrollTop", offsetBottom );
                            if( frameHeight <= elem.attr('height') )
                            {
                                frame.scrollTop( offsetBottom - frameHeight );
                                // frame.attr( "scrollTop", offsetBottom - frameHeight );
                            }else {
                                frame.scrollTop( offsetBottom );
                            }
                    }
            }
        }
    
        $('#buttonTest1').click(function(){
            var scrollElement = $('#childSlide1');
            keepScrolledOver(scrollElement);
        });
    
        $('#buttonTest2').click(function(){
            var scrollElement = $('#childSlide2');
            keepScrolledOver(scrollElement);
        });     
    });