【问题标题】:Absolutely positioned div inside scroll div moves jumpily滚动 div 内绝对定位的 div 跳跃式移动
【发布时间】:2013-06-15 02:59:26
【问题描述】:

我知道有类似的问题,但到目前为止我还没有找到解决问题的方法。这个jsfiddle 反映了我的要求。

为了解释,一个 div 中有几个垂直堆叠的 view-div(溢出)。每个 view-div 都有一个 label-div,应该显示在左上角。如果视图 div 水平滚动,则标签应保持在视图中。当视图垂直滚动时,向上消失的视图应该将它的标签向下推,直到它完全消失。

这个 jsfiddle 示例中没有的另一个要求是 view-div 可以垂直调整大小(我已经准备好该代码,但我认为它对于这个示例来说太大了)。

现在,我实现它的方式不起作用。标签移动不够顺畅。我真的希望它们粘在容器 div 的边缘。此外,当您快速向上滚动时,标签不会出现在左上角。

其他一些 SO 问题/答案建议我应该根据滚动方向在固定定位和绝对定位之间切换。但我认为这行不通,因为用户可以同时水平和垂直拖动滚动背景。

我希望$labels.css({"left" : scrLeft}) 方法能够简单地工作,这似乎是合理的。 :-) 我尝试简化my example,但那里的动作也太跳跃了。

有什么想法吗?谢谢!!

【问题讨论】:

    标签: jquery css html scroll


    【解决方案1】:

    概念证明解决方案

    这是一个巧妙的小问题,它确实迫使您考虑控制布局几何的各种重叠坐标系。

    这里是 jQuery

    //handle scrolling
    var $labels = $(".label");
    
    $("#container").on("scroll", function () {
    
        //horizontal
        var scrLeft = $(this).scrollLeft();
        $labels.css({
            "left": scrLeft
        });
    
        //vertical
        var scrollTop    = $("#container").scrollTop();
        var containerTop = $('#container').position().top;
        var innerTop = $('#inner_container').position().top;
        var views = $("#inner_container .view");
        var diff = 0;
        var heightAggr = 0;
    
        if (scrollTop == 0) {
            views.children(".label").css({
                "top": 0
            });
        }
    
        views.children(".label").removeClass('highlight');
        for (var i = 0; i < views.length; i += 1) {
            var view = $(views[i])
            var viewHeight = view.outerHeight();
            var viewTop = view.offset().top;
    
            /* This is the key parameter to test... 
               getting this relationship right took a lot of effort,
               everything else was relatively easy... */
            diff = scrollTop - viewTop + innerTop;
    
            if (diff>0) {
                view.children(".label").addClass('highlight');
                var labelOffset = scrollTop - heightAggr;
                var maxOffset = view.height() 
                                - view.children(".label").outerHeight();
    
                /* The following pins the label to the bottom of the
                   view when view is about to scroll off the screen... */
                var labelPosition = Math.min(labelOffset,maxOffset); 
    
                view.children(".label").css({
                "top": labelPosition
                });
            } else {
                view.children(".label").css({ /* Clean up when         */
                "top": 0                      /* reverse scrolling ... */
                });
            }
            /* will allow .view with variable heights... */
            heightAggr += viewHeight; 
        }
    });
    

    演示小提琴位于:http://jsfiddle.net/audetwebdesign/HRnCf/

    浏览器免责声明

    我只在 Firefox 中测试过这个...

    【讨论】:

    【解决方案2】:

    你应该使用固定位置:

    http://jsfiddle.net/mHWJH/1/

    var $label1 = $("#label1"),
        offsetTop = $label1.offset().top,
        offsetLeft = $label1.offset().left,
        $label2 = $("#label2"),
        offsetTop2 = $label2.offset().top,
        offsetLeft2 = $label2.offset().left;
    
    $("#container").on("scroll", function() {
    
        var scrLeft = $(this).scrollLeft();
        $label1.css({
            position:'fixed',
            top:offsetTop,
            left:offsetLeft
        });
         $label2.css({
            position:'fixed',
            top:offsetTop2,
            left:offsetLeft2
        });
    });
    

    【讨论】:

    • 是的,我知道这适用于简单的示例。真实的例子(见我的问题的第一段)涉及更多。
    猜你喜欢
    • 2018-12-05
    • 1970-01-01
    • 1970-01-01
    • 2011-02-21
    • 1970-01-01
    • 1970-01-01
    • 2015-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多