优化JavaScript以实现自动滚动功能 [英] Optimizing javascript for auto scroll feature

查看:106
本文介绍了优化JavaScript以实现自动滚动功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Knowing only enough javascript and jquery to be dangerous, I cargo-culted some javascript code for a table of contents in a left sidebar that corresponds to the content in a content area. The table of contents scrolls automatically to reflect where in the content the user is. You can see a live demo here.

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

I'm fairly pleased with it so far but the javascript that scrolls the table of contents is a bit laggy. You'll notice it on the live demo if you scroll up and down in the main content area a few times. I'd like know what I can to do make it a lot snappier. Also, when scrolling quickly to the top and bottom, the table of contents doesn't accurately reflect the user is at the top and bottom of the document. Here is the relevant js from the demo:

$(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',
          });
        }
      }
    })

});

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

I'm pretty sure the issue is that the function gets called every time the main contents are scrolled which is inefficient. I'm not sure what I can try to mitigate this.

推荐答案

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

Here's what I ended up doing. I call a function every 4/10ths of second instead of detecting scrolls. The function checks the current position against the positions of the elements which are calculated just once before the function is called so it's much quicker. Things are very snappy now. Code is a bit of a mess but seems to do the trick.

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

这篇关于优化JavaScript以实现自动滚动功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆