jQuery滚动计算在高速滚动时不准确

时间:2011-01-16 22:38:24

标签: jquery css performance scroll precision

我遇到了很奇怪的事情。我的代码中出错的可能性很高,但我无法弄清楚它为什么会发生。

首先,这是一个示例页面: 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; }

非常感谢任何想法等。

谢谢! -David

2 个答案:

答案 0 :(得分:0)

`我猜你得到的事件比你的回调可以处理它们的速度快,这可能导致多次调用你的回调立即运行,也许他们互相争斗。

尝试这样一个简单的警卫:

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 and .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_marginmargin_top变量,然后将它们丢弃。

答案 1 :(得分:0)

我重新安排了代码并找到了一个可行的解决方案:

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>

这些事件似乎发生的速度比回调可以处理的要快(请参阅mu太短的答案),但似乎总是找到正确的位置。