高性能的JavaScript固定滚动

4

我已经阅读了无数的帖子并重写了无数次代码,但是还是遇到了困难。我正在尝试克服不使用CSS来固定元素位置时的限制,原因是容器应用了CSS scale3d变换。虽然我的最新解决方案有效,但有时仍然容易出现“卡顿”和“滞后”问题,主要发生在初始滚动时(似乎某些滚动“惯性”可以提高表现)。这个项目是重写一个旧的Ember应用程序,而在那个应用程序中,同样的功能运行得非常完美。我已经通过反混淆的Ember代码,一直尝试找到实现这一点所采用的魔法(但没有成功)。

这是迄今为止表现最佳的最新版本:

const handler = () => {
  const scroll = window.scrollY,
    // provides scaling factor from container
    scaled = scroll / scalingObject.current.scale;

  requestAnimationFrame(() => {
    $("div[data-sb-active-page='true'] .sb-fixed-scroll").each(function () {
      const $el = $(this),
        // a previous (non-translate3d) transform may have been cached
        ot = $el.data('sb-original-transform');
      $el.css({
        transform: `translate3d(0px, ${scaled}px, 0px) ${ot}`,
      });
    });
  });
};
$(window).on('scroll', handler);

为了避免一些评论:我已经尝试过这段代码,而不必担心应用前一个变换的问题。
$("div[data-sb-active-page='true'] .sb-fixed-scroll").css({
   transform: `translate3d(0px, ${scaled}px, 0px)`
});

我尝试了直接使用 DOM 构造 - 使用 document.querySelectorAll 然后迭代元素,调用 element.style.transform = `translate3d(0px, ${scaled}px, 0px)`

这些解决方案都可行 - 而且 jQuery (令我惊讶的是) 似乎是最好的 - 但不是完美的。正如先前所述,如果我没有见过一个仅使用 JS 的解决方案在没有卡顿/抖动的情况下工作,我会认为它是不可能完成的。

这是我的心头之患 - 欢迎任何指导。

更新 - 创建了一个简单的 JSFiddle:https://jsfiddle.net/syzmic/sbwac5zq/3/

我从当前项目中滚动最困难的页面中提取了 HTML。我包含了当前状态的 JS。大部分时间它都有效... 但是快速滚动鼠标可能会导致卡顿或弹跳。


2
首先,缓存DOM是一个好的开始:在开头将DOM元素存储在变量中并重复使用该变量,而不是在每次迭代中查找整个文档中的这些元素。此外,即使可能不会注意到,jQuery始终比本机JS效率低(需要执行更多代码)。话虽如此,您能否发布一个最小可重现示例(带有HTML),以便我们可以轻松地重现问题,而无需自己设置所有内容,并进行分析? - blex
首先,从.sb-fixed-scroll元素中删除transition属性,它会导致动画延迟。此外,请尝试从代码编辑器中删除不必要的代码。这样做非常难以隔离问题。 - Mosh Feu
1个回答

0

所以-缺少的关键是这个:

https://github.com/drojdjou/bartekdrozdz.com/blob/master/static/src/framework/VirtualScroll.js

普通的JS滚动根本不是答案。我正在重写的项目从以下博客文章中获取了一些想法,并将它们适配到Ember中(我必须进行一些严肃的代码考古才能找到它):

http://www.everyday3d.com/blog/index.php/2014/08/18/smooth-scrolling-with-virtualscroll/

在我的重写中,我采用了类似的方法,滚动变得流畅而稳定。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接