Абсолютно позициониран div вътре в превъртане div се движи рязко

Знам, че е имало подобни въпроси, но досега не съм намерил начин да реша проблема си. Този jsfiddle отразява моите изисквания.

За да обясня, има няколко вертикално подредени view-div вътре в div (което прелива). Всеки view-div има label-div, който трябва да се показва в горния ляв ъгъл. Ако view-div се превъртат хоризонтално, етикетите трябва да останат в изгледа. Когато изгледите се превъртат вертикално, изгледът, който изчезва нагоре, трябва да има етикет, натиснат надолу, докато изчезне напълно.

Друго изискване, което не е в този пример за jsfiddle, е view-div да могат да променят размера си вертикално (имам този код готов, но го сторих твърде голям за този пример).

Сега начинът, по който го внедрих, не работи. Етикетите не се движат достатъчно гладко. Наистина ги искам да бъдат залепени за ръба на контейнера div. Освен това, когато превъртите бързо нагоре, етикетите не попадат в горния ляв ъгъл.

Някои от другите въпроси/отговори на SO предполагат, че трябва да превключвам между фиксирано и абсолютно позициониране, в зависимост от посоката на превъртане. Но не мисля, че това ще работи, защото потребителят може да плъзга превъртащия фон хоризонтално и вертикално едновременно.

Надявах се подходът $labels.css({"left" : scrLeft}) просто да проработи, изглеждаше разумен. :-) Опитах се да опростя моя пример, но и там движението е твърде рязко.

Някакви идеи? Благодаря!!


person devboell    schedule 09.06.2013    source източник


Отговори (2)


Доказателство за концептуално решение

Това е спретнат малък проблем, който наистина ви принуждава да мислите за различните припокриващи се координатни системи, които контролират геометрията на оформлението.

Ето 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...

person Marc Audet    schedule 14.06.2013
comment
Между другото, може да искате да разгледате следното stackoverflow.com/questions/17138438/ Друг пример за jQuery, върху който работих вчера. Първо вземи кафе... - person Marc Audet; 17.06.2013

Трябва да използвате фиксирана позиция:

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
    });
});
person A. Wolff    schedule 09.06.2013
comment
да, разбирам, че това ще работи за простия пример. Истинският пример (вижте първия абзац на въпроса ми) е малко по-замесен. - person devboell; 09.06.2013