0

我正在整理一个 jQuery 插件。该插件采用面板,并自动调整它们的高度。所以我从这样的事情开始:

<div class="panel">Test 1</div>
<div class="panel">Test 2</div>
<div class="panel">Test 3</div>

代码看起来像:

    sizePanels: function(){
      panels.each(function(){
        $(this).height(docHeight);
      });
    },

有一个向下按钮,单击该按钮时,会将用户带到下一个 $(".panel):

nextPanel: function(){
  $.scrollTo($(".panel:eq(" + panelIndex + ")"), 250, { easing: "swing" });
}

有了这个,我正在跟踪他们所在的面板索引:

    if (panelIndex < (panelCount - 1) ) {
      panelIndex += 1;
    }

我试图找出一种方法来跟踪它们是否碰巧手动滚动,并传递其中一个元素,然后增加“panelIndex”,这样按钮就不会向上移动而不是向下移动,因为它从来没有由于用户使用滚动条而不是按钮而正确递增。这是我到目前为止所拥有的:

   $(window).scroll(function(){
    panels.each(function(index){
      if ($(window).scrollTop() > $(this).scrollTop()) { 
        panelIndex = index; 
        // console.log(index);
      }
    });

    if (panelIndex < panelCount - 1){
      s.showDownButton();
    }
  });

代码过度检查并且感觉有些过火。有更好的方法吗?

4

1 回答 1

1

一个简单的优化是只计算一次 scrollTop 并在找到匹配时退出每个循环。您可以通过返回 false 来退出 $.each 循环。

$(window).scroll(function(){
    var scrollTop = $(window).scrollTop();
    panels.each(function(index){
        if (scrollTop > $(this).scrollTop()) { 
            panelIndex = index; 
        } else {
            return false;
        }
    });

    if (panelIndex < panelCount - 1){
        s.showDownButton();
    }
});

我建议优化的下一个方法是在页面加载时(以及调整视口大小时)预先计算每个面板的 scrollTop。如果将这些值存储在数组中,则可以非常快速地循环它们。

这里有一些粗略的代码来说明这个想法:

var panelTops = [];

findPanelTops(); // calculate on load
$(window).on("resize", findPanelTops); // calculate on resize

function findPanelTops() {
    panelTops = [];
    panels.each(function(index) {
        panelTops.push($(this).scrollTop());
    });
}

$(window).scroll(function(){
    var scrollTop = $(window).scrollTop();
    for (var i = 0; i < panelTops.length; i++) {
        if (scrollTop > panelTops[i]) { 
            panelIndex = i;
        } else {
            break;
        }
    };

    if (panelIndex < panelCount - 1){
        s.showDownButton();
    }
});

滚动事件可以非常快速地触发,因此您希望尽可能减少计算量。解决所有这些问题的一种方法是实现一个滚动端处理程序。这只会在滚动事件似乎已经停止时触发。

这是执行此操作的一些基本代码。当滚动事件停止超过 500 毫秒时,它将触发:

var scrollTimeout = null;

function onScroll() {
    if (scrollTimeout) {
        clearTimeout(scrollTimeout);
    }
    scrollTimeout = setTimeout(onScrollEnd, 500);
}

function onScrollEnd() {
    // Scrolling has stopped
    // Do stuff ...

   scrollTimeout = null;
}

$(window).on("scroll", onScroll);
于 2012-05-15T05:03:48.047 回答