绝对定位的div内滚动div快速移动 [英] Absolutely positioned div inside scroll div moves jumpily

查看:235
本文介绍了绝对定位的div内滚动div快速移动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



这个jsfiddle示例中不需要的另一个要求是view-div可以垂直调整大小(我已经准备好了代码,但我认为这个例子太大了)。



现在,我实现它工作。标签不能平滑移动。我真的希望他们粘到容器div的边缘。



一些其他SO问题/答案建议我应该在固定和绝对定位,取决于滚动方向。但我不认为这将工作,因为用户可以同时拖动水平和垂直滚动背景。



我希望 $ labels.css({left:scrLeft})方法只是工作,似乎是合理的。 :-)我试着简化我的例子,但也有运动太疯狂。



有什么想法吗?感谢!!

解决方案

概念证明解决方案





这里是 jQuery / p>

  //处理卷动
var $ labels = $(。label);

$(#container)。on(scroll,function(){

// horizo​​ntal
var scrLeft = $(this).scrollLeft ();
$ labels.css({
left:scrLeft
});

// vertical
var scrollTop = #container)。scrollTop();
var containerTop = $('#container')。position()。top;
var innerTop = $('#inner_container')。position ;
var views = $(#inner_container .view);
var diff = 0;
var heightAggr = 0;

if(scrollTop == 0 ){
views.children(。label)。css({
top:0
});
}

视图。对于(var i = 0; i var view = $(views [...] i])
var viewHeight = view.outerHeight();
var viewTop = view.offset()。top;

/ *这是测试的关键参数。 。
获得这种关系需要付出很多努力,
其他一切都比较容易... * /
diff = scrollTop - viewTop + innerTop;

if(diff> 0){
view.children(。label)。addClass('highlight');
var labelOffset = scrollTop - heightAggr;
var maxOffset = view.height()
- view.children(。label)。outerHeight();

/ *当视图正在滚动屏幕时,下面的引号将标签放在
视图的底部... * /
var labelPosition = Math.min labelOffset,maxOffset);

view.children(。label)。css({
top:labelPosition
});
} else {
view.children(。label)。css({/ *清除* /
top:0 / * reverse scrolling ... * /
});
}
/ *将允许.view与可变高度... * /
heightAggr + = viewHeight;
}
});

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



浏览器免责声明 / p>

我只在Firefox ...


中测试过

I know there have been similar questions, but so far I have not found a way to fix my problem. This jsfiddle reflects my requirement.

To explain, there are several vertically-stacked view-divs inside a div (which overflows). Each view-div has a label-div which should be displayed in the top-left corner. If the view-divs are scrolled horizontally, the labels should remain in view. When the views are scrolled vertically, the view that is disappearing upwards should have it label pushed down until it completely disappears.

Another requirement which is not in this jsfiddle example is that the view-divs are resizable vertically (I have that code ready, but I thought it too large for this example).

Now, the way I implemented it doesn't work. The labels do not move smoothly enough. I really want them glued to the edge of the container div. Also when you scroll upwards quickly, the labels don't land in the top-left corner.

Some of the other SO questions/answers suggest I should toggle between fixed and absolute positioning, depending on the scroll direction. But I don't think this will work, because the user can drag the scrolling background horizontally and vertically at the same time.

I was hoping the $labels.css({"left" : scrLeft}) approach would simply work, it seemed reasonable. :-) I tried simplifying my example but there too the movement is way too jumpy.

Any ideas? Thanks!!

解决方案

Proof of Concept Solution

This is a neat little problem that really forces you to think in about the various overlapping coordinate systems that control the layout geometry.

Here is the 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; 
    }
});

The demo fiddle is at: http://jsfiddle.net/audetwebdesign/HRnCf/

Browser Disclaimer

I only tested this in Firefox...

这篇关于绝对定位的div内滚动div快速移动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆