跟踪元素之外的滚动位置

时间:2012-05-15 03:44:24

标签: javascript jquery dom

我正在整理一个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();
    }
  });

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

1 个答案:

答案 0 :(得分: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();
    }
});

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

这是执行此操作的一些基本代码。滚动事件停止超过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);