优化JavaScript以实现自动滚动功能

时间:2018-10-29 06:17:05

标签: javascript jquery

我只知道足够多的javascript和jquery才是危险的,所以我在左侧边栏中为与内容区域中的内容相对应的目录中的内容编写了一些javascript代码。目录自动滚动以反映用户在内容中的位置。您可以看到live demo here.

到目前为止,我对此感到非常满意,但是滚动目录的javascript有点落后。如果在主内容区域中上下滚动几次,您将在实时演示中注意到它。我想知道我能做些什么使它变得更加敏捷。同样,当快速滚动到顶部和底部时,目录不能正确反映用户位于文档的顶部和底部。这是演示中的相关js:

$(window).bind('scroll', function() {
    var currentTop = $(window).scrollTop();
    var elems = $('.scrollspy');
    elems.each(function(index){
      var elemTop   = $(this).offset().top;
      var elemBottom   = elemTop + $(this).height();
      if(currentTop + 2 >= elemTop && currentTop <= elemBottom){ // pad by 2px to ensure active
        var id     = $(this).attr('name');
        var navElem = $('a[href="#' + id + '"]');
        navElem.addClass('active').siblings().removeClass( 'active' );
        var dft = navElem[0].getBoundingClientRect().top; // distance from top of viewport
        var s = $('#sidebar');
        if (dft > s.innerHeight() * .5 || dft < s.scrollTop() ) {
          $('#sidebar').animate({
              scrollTop: navElem.offset().top - s.offset().top + s.scrollTop() - s.innerHeight()/2,
              duration: 1,
              ease: 'linear',
          });
        }
      }
    })

});

我很确定问题是每次滚动主要内容时都会调用该函数,这效率很低。我不确定该如何减轻这种情况。

1 个答案:

答案 0 :(得分:0)

这就是我最终要做的。我每4/10秒调用一次函数,而不是检测滚动。该函数对照调用该函数之前一次计算出的元素的位置来检查当前位置,因此它要快得多。事情现在非常活泼。代码有点混乱,但似乎可以解决问题。

window.setInterval(function(){
  autoscroll();
}, 400);
var elems = $('.scrollspy');
var headers = {};
var headers_pos = [];
elems.each(function(index){
  var pos = $(this).position().top - 70;

  var name = $(this).attr('name');
  pos_str = Math.floor(pos);
  headers[pos_str] = name;
  headers_pos.push(pos_str);
});
headers_pos.sort(function(a, b) {return a-b});
var current_active = $("#sidebar a:first");
current_active.addClass('active');

function autoscroll() {
    var scrollTop = $(window).scrollTop(),
        elementOffset = $('#content').offset().top,
        distance = Math.abs(elementOffset - scrollTop);

    var id;
    var last = $('#sidebar a:first').attr('href');
    headers_pos.forEach(function(index) {
      if (index > distance) {
        id = last;
        return;
      } else {
        last = '#' + headers[index];
      }
    });
    if (!id) {
      id = last;
    }


    var navElem = $('a[href="' + id + '"]');
    navElem.addClass('active')
    if (!current_active.is(navElem)) {
      current_active.removeClass( 'active' );
    }
    current_active = navElem;
    var dft = navElem[0].getBoundingClientRect().top; // distance from top of viewport
    var s = $('#sidebar');
    if (dft > s.innerHeight() * .5 || dft < s.scrollTop() ) {
      $('#sidebar').animate({
            scrollTop: navElem.offset().top - s.offset().top + s.scrollTop() - s.innerHeight()/2,
            duration: 1,
            ease: 'swing',
      });
    }
}