【问题标题】:Optimizing javascript for auto scroll feature为自动滚动功能优化 javascript
【发布时间】:2018-10-29 06:17:04
【问题描述】:

知道只有足够的 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',
          });
        }
      }
    })

});

我很确定问题是每次滚动主要内容时都会调用该函数,这是低效的。我不确定我可以尝试什么来缓解这种情况。

【问题讨论】:

  • 一种技术可以“节流”。在此处阅读更多信息devdocs.io/lodash~4/index#throttle
  • 只要去掉滚动的过渡时间,就大功告成了……
  • @BuggyParadox 我已经消除了animate 方法,但它有点不和谐和迷失方向。希望保持流畅的滚动效果。
  • 我将检查 lodash 作为最后的手段。但宁愿看看我是否可以避免另一个插件。可能会加快速度的一件事是在页面加载后将元素存储在数组中,这样 js 就不必每次都搜索它们。
  • 是的,将它们放入函数外部的数组中肯定会有所帮助。不完美,但更好。

标签: javascript jquery


【解决方案1】:

这就是我最终要做的。我每 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',
      });
    }
}

【讨论】:

  • 破坏此代码的一件事是,如果用户通过放大或缩小来调整浏览器中的字体大小。有没有办法用js检测这个事件?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多