Расчеты jQuery-прокрутки неточны при высокоскоростной прокрутке - PullRequest
2 голосов
/ 17 января 2011

Я столкнулся с чем-то очень странным.Вероятность того, что это ошибка в моем коде, высока, но я не могу понять, почему это происходит.

Во-первых, вот пример страницы: http://designintellection.com/quotes/2011/jan/13/design-thinking-visual/

Если вы заметили дваНавигационные вкладки в правой части страницы, когда вы прокручиваете их вниз, уменьшаются в размере, а затем становятся позиционными: фиксируются при прокрутке вниз по остальной части страницы.Когда вы прокручиваете назад вверх, они увеличиваются до своего первоначального размера и возвращаются к нефиксированному позиционированию.(Если вам интересно, почему я сокращаю их, я в конечном итоге собираюсь заменить текст значком.)

Я разместил код (JS & CSS) для достижения этого эффекта ниже.Я знаю, что это может быть написано лучше, но главное, что я пытаюсь различить, это то, что Javascript способен захватывать каждую конкретную позицию прокрутки.Я говорю это потому, что если вы прокручиваете медленно, то вкладки ведут себя так, как они должны, вы можете перемещаться вверх и вниз сколько угодно.Однако, если вы прокручиваете с нормальной до быстрой скорости, то размер, поля и расположение распадаются, и вы получаете очень странное поведение.

На каком-то уровне мне кажется, что я принимаю сумасшедшие таблетки, обычно я стараюсьискать ошибки и т. д., но мне кажется настолько странным, что он работает при медленной прокрутке и не работает при быстрой прокрутке.

jQuery:

    $(function() {
    $(window).scroll(function() {
        var scroll = $(window).scrollTop();

        if (scroll > 80) {
            $("#the-portfolio-link").css({"width":"2px", "margin-top":"0"});
            $("#the-portfolio-link").addClass("page-link-portfolio-stay");
            $("#the-services-link").css({"margin-top":"108px"});
        }

        if ((scroll >= 22) && (scroll < 80)) {
            $("#the-portfolio-link").css({"width":"60px", "margin-top":"65px"});
            $("#the-portfolio-link").removeClass("page-link-portfolio-stay");

            var new_width = 60 + (22 - scroll);
            var existing_margin = 65;
            var new_margin_services = 65 - (60 - new_width);

            if (existing_margin < 65) {
                var new_margin = 65 - (67 - new_width);
                var margin_top = new_margin;
            }
            else {
                var margin_top = 65;
            }

            $("#the-portfolio-link").css({"width":new_width+"px", "margin-top":margin_top+"px"});
            $("#the-services-link").css({"margin-top":new_margin_services+"px"});
        }

        if ((scroll > 80) && (scroll <= 138)) {
            $("#the-services-link").css({"width":"60px", "margin-top":"108px"});
            $("#the-services-link").removeClass("page-link-services-stay");

            var new_services_width = 60 + (80 - scroll);
            var existing_services_margin = $("#the-services-link").css("margin-top").replace("px","");

            var margin_services_top = 108 + (60 - new_services_width);

            $("#the-services-link").css({"width":new_services_width+"px", "margin-top":margin_services_top+"px"});
        }

        if (scroll > 138) {
            $("#the-services-link").css({"width":"2px", "margin-top":"0"});
            $("#the-services-link").addClass("page-link-services-stay");
        }
    });
});

CSS (соответствующий кодтолько):

.main-nav { position:absolute; left:1102px; top:55px; }
.main-nav-link { display:block; width:60px; height:22px; margin:65px 0 0 36px; }

.page-link-portfolio-stay { width:2px; margin-top:0; position:fixed; left:1102px; top:40px; overflow:hidden; }
.page-link-services-stay { width:2px; margin-top:0; position:fixed; left:1102px; top:83px; overflow:hidden; }

Любые идеи и т. д. очень ценятся.

Спасибо!-Давид

Ответы [ 2 ]

0 голосов
/ 17 января 2011

Я изменил код и нашел работоспособное решение:

jQuery:

jQuery.fn.main_nav_behavior = function(nav_id, class_apply, orig_margin_top, nav_order, nav_order_magnitude) {
    $(window).scroll(function() {
        var scroll = $(window).scrollTop();

        if ((scroll >= 22) && (scroll <= 80)) {
            var new_width = 60 + (22 - scroll);
            var existing_margin = $(nav_id).css("margin-top").replace("px","");

            if ((existing_margin < orig_margin_top) && ($(nav_id).hasClass(class_apply))) {
                var new_margin = (orig_margin_top - nav_order_magnitude) - ((orig_margin_top + 2) - (new_width*nav_order));
                var margin_top = new_margin;
            }
            else {
                if (nav_order_magnitude == 0) {
                    var margin_top = orig_margin_top;
                }
                else {
                    var new_margin = orig_margin_top - ((60 - new_width)*(nav_order-1));
                    var margin_top = new_margin;
                }
            }

            $(nav_id).css({"width":new_width+"px", "margin-top":margin_top+"px"});
        }
        else if (scroll > 80) {
            $(nav_id).css({"width":"2px", "margin-top":"0"});
            $(nav_id).addClass(class_apply);
        }
        else {
            $(nav_id).css({"width":"60px", "margin-top":orig_margin_top+"px"});
            $(nav_id).removeClass(class_apply);
        }
    });
}

$(function() {
    $(".main-nav").main_nav_behavior("#the-portfolio-link", "page-link-portfolio-stay", 65, 1, 0);
    $(".main-nav").main_nav_behavior("#the-services-link", "page-link-services-stay", 166, 2, 2);
    $(".main-nav").main_nav_behavior("#the-blog-link", "page-link-blog-stay", 267, 3, 4);
});

CSS:

.main-nav-link { display:block; width:60px; height:22px; margin:65px 0 0 36px; padding:7px 20px 5px 20px; position:absolute; overflow:hidden; }

.page-link-portfolio { margin-top:65px; }
.page-link-services { margin-top:166px; }
.page-link-blog { margin-top:267px; }

.page-link-portfolio-stay { width:2px; margin-top:0; position:fixed; left:1102px; top:40px; overflow:hidden; }
.page-link-services-stay { width:2px; margin-top:0; position:fixed; left:1102px; top:83px; overflow:hidden; }
.page-link-blog-stay { width:2px; margin-top:0; position:fixed; left:1102px; top:126px; overflow:hidden; }

HTML:

<nav class="main-nav">
  <ul class="main-nav-list">
    <li class="main-nav-item"><a id="the-portfolio-link" class="page-link-portfolio main-nav-link" href="/portfolio/v6/">Portfolio</a></li>
    <li class="main-nav-item"><a id="the-services-link" class="page-link-services main-nav-link" href="/services/v6/">Services</a></li>
    <li class="main-nav-item"><a id="the-blog-link" class="page-link-blog main-nav-link" href="/services/v6/">Blog</a></li>
  </ul>
</nav>

Похоже, что события происходят быстрее, чем могут обработать обратные вызовы (см. Мю слишком короткий ответ), но всегда кажется, что они находятся в правильном месте.

0 голосов
/ 17 января 2011

`Я полагаю, что вы получаете события быстрее, чем ваш обратный вызов может с ними справиться, что может привести к одновременному выполнению нескольких вызовов вашего обратного вызова и, возможно, они сражаются друг с другом.

Попробуйте простой охранник, подобный этому:

var busy = false;
$(window).scroll(function() {
    if(busy)
        return;
    busy = true;
    var scroll = $(window).scrollTop();

    //...

    if (scroll > 138) {
        $("#the-services-link").css({"width":"2px", "margin-top":"0"});
        $("#the-services-link").addClass("page-link-services-stay");
    }
    busy = false;
});

и посмотри, что получится. Если это исправит это, то, по крайней мере, вы будете знать, в чем проблема. Этот защитный хак не является решением, конечно, это просто быстрая и простая отладочная помощь, которая поможет вам понять, в чем проблема. Реальным решением, вероятно, было бы управление очередью событий самостоятельно с помощью .queue и .dequeue.

Вы также можете создать все свои объекты jQuery вне обратного вызова, поставить в очередь кучу изменений CSS и классов внутри обратного вызова, а затем применить все изменения в одном блоке в конце. Это не решит вашу проблему, но уменьшит количество конфликтов и раздоров.

Кстати, этот фрагмент кода не делает ничего полезного:

    if(existing_margin < 65) {
        var new_margin = 65 - (67 - new_width); 
        var margin_top = new_margin;  
    }
    else {
        var margin_top = 65;  
    }

Вы определяете новые переменные new_margin и margin_top внутри ветвей, а затем выбрасываете их.

...