2011-01-16 5 views
2

Ich habe in etwas sehr merkwürdig geraten. Die Wahrscheinlichkeit, dass es ein Fehler in meinem Code ist, ist hoch, aber ich kann nicht herausfinden, warum es passiert.jQuery Scroll-Berechnungen bei High-Speed-Scrolling ungenau

Zunächst ist hier eine Beispielseite: http://designintellection.com/quotes/2011/jan/13/design-thinking-visual/

Wenn Sie die beiden nav Registerkarten auf der rechten Seite der Seite bemerken, wenn Sie sie in der Größe schrumpfen nach unten scrollen und dann Position werden: fest, wie Sie die nach unten scrollen Rest der Seite. Wenn Sie nach oben scrollen, werden sie auf ihre ursprüngliche Größe vergrößert und kehren zu einer nicht fixierten Positionierung zurück. (Wenn Sie sich wundern, warum ich sie schrumpfe, werde ich schließlich den Text durch ein Symbol ersetzen.)

Ich habe den Code (JS & CSS) veröffentlicht, um diesen Effekt unten zu erreichen. Ich weiß, dass es besser geschrieben werden kann, aber die Hauptsache, die ich versuche zu unterscheiden, ist, ob Javascript in der Lage ist, jede bestimmte Scroll-Position zu erfassen. Ich sage das, weil, wenn Sie langsam scrollen, dann die Registerkarten sich so verhalten, wie sie sollen, können Sie auf und ab so viel gehen, wie Sie mögen. Wenn Sie jedoch mit einer normalen bis schnellen Geschwindigkeit scrollen, fallen die Größe, die Ränder und die Positionierung auseinander und Sie erhalten ein sehr merkwürdiges Verhalten.

Auf einer Ebene fühle ich mich wie ich verrückte Pillen nehme, normalerweise würde ich versuchen, nach Fehlern usw. zu suchen, aber es scheint so seltsam, dass es funktioniert, wenn Sie langsam scrollen und nicht, wenn Sie schnell scrollen .

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 (Kennziffer only):

.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; } 

Irgendwelche Ideen usw. sind sehr geschätzt.

Danke! -David

Antwort

0

ich neu geordnet den Code und fand eine praktikable Lösung:

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> 

Die Ereignisse zu sein scheinen passiert schneller als der Anruf Rückseiten können damit umgehen (siehe die Antwort von mu ist zu kurz), aber sie scheint sich immer an der richtigen Stelle niederzulassen.

0

`Ich nehme an, dass Sie Ereignisse schneller erhalten, als Ihr Callback mit ihnen umgehen kann, die mehrere Anrufe zu Ihrem Callback verursachen können, um sofort ausgeführt zu werden, und vielleicht bekämpfen sie sich gegenseitig.

eine einfache Wache wie diese versuchen:

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; 
}); 

und sehen, was passiert. Wenn das das Problem löst, dann weißt du zumindest, was das Problem ist. Dieser Schutz-Hack ist natürlich keine Lösung, sondern nur eine schnelle und einfache Debug-Hilfe, die Ihnen hilft, das Problem zu erkennen. Eine echte Lösung wäre wahrscheinlich, die Ereigniswarteschlange selbst mit .queue and .dequeue zu verwalten.

Sie können auch alle Ihre jQuery-Objekte außerhalb des Callbacks erstellen, eine Reihe von CSS- und Klassenänderungen innerhalb des Callbacks in die Warteschlange stellen und dann am Ende alle Änderungen in einem Block übernehmen. Das würde Ihr Problem nicht lösen, aber es würde die Menge an Konflikten und Konflikten reduzieren.

BTW, dieses Stück Code tut nichts überhaupt nützlich:

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

Sie definieren neue new_margin und margin_top Variablen in den Zweigen und dann wegzuwerfen.

+0

Ich versuchte diese Wache und das Verhalten änderte sich nicht. Danke, dass Sie meine ursprüngliche Sorge ausgeschlossen haben. Ich denke, dass es etwas mit meinen bedingten Aussagen zu tun hatte. Ich bin mir nicht sicher. Ich ging von einer Reihe von ifs zu if, elseifs und anderen und das schien es zu beheben. Obwohl ich denke, dass die Ereignisse immer noch zu schnell für die Callbacks sind (ich habe variable Ausgaben beobachtet, die linear sein sollten und sie überall herumgeprallt sind.) Es hätte jedoch etwas anderes sein können, als ich die Bedingungen neu arrangierte, nicht sicher. Ich habe den Code ziemlich schnell geändert. –

+0

Der Wächter funktioniert nicht, weil Sie die gleichzeitige Ausführung von Javascript im Browser nie sehen werden. Soweit es Ihren Code betrifft, ist es immer single-threaded. –