且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

绝对定位的div内滚动div快速移动

更新时间:2022-10-21 09:57:20

概念证明解决方案





这里是 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...