首页 > 解决方案 > 为什么添加不可见的非交互式覆盖会提高滚动同步的性能?[铬合金]

问题描述

我需要同步两个元素的滚动:一个内容区域和一个“标题”。

但是当我使用该scroll事件通过 CSS 更改另一个元素的位置时,transform在用户滚动和标题移动之间存在明显的延迟,这会让人分心,尤其是在 Chrome 上。

但是,与使用相同方法同步滚动位置的其他应用程序相比,他们没有。经过几个小时试图找出原因,我终于找到了:它们有一个覆盖整个滚动区域的不可见覆盖层,这也是非交互式的(CSS pointer-events: none

我在下面准备了一个游乐场,覆盖层是可见的,并且没有覆盖整个区域,因此可以轻松进行比较。

至少这种行为发生在我的机器上,一台带有 Chrome 的 Mac,我滚动触控板手势。还需要有一些负载,所以这个片段还每 100 毫秒添加一个 30 毫秒的阻塞循环来模拟一个

const content = document.getElementById("content");
const header = document.getElementById("header");

// Add content
const helloes = new Array(100).fill("Hello!").join("<br /><br />");
header.innerHTML = content.innerHTML = helloes;

// Synchronize scroll of content to header by adding `transform`
content.addEventListener("scroll", (evt) => {
  header.style.transform = `translateY(${-content.scrollTop}px)`;
});

// Simulates performance hit, either low-end computer or a component doing extra load
setInterval(() => {
  let start = Date.now();
  while (Date.now() < start + 30);
}, 120);
.main {
  position: relative;
  display: flex;
}

.main>div {
  overflow: auto;
  height: 200px;
  padding: 10px;
  border: 1px solid black;
  border-radius: 5px;
  white-space: nowrap;
}

#content {
  padding-right: 200px;
}

#overlay {
  position: absolute;
  left: 160px;
  top: 50px;
  width: 100px;
  height: 100px;
  box-sizing: border-box;
  background: rgba(0, 0, 0, 0.3);
  pointer-events: none;
}
<div class="main">
  <div>
    <div id="header">
    </div>
  </div>
  <div id="content">
  </div>

  <div id="overlay"></div>
</div>

由于重现可能非常棘手,因此我在此图像中记录了此行为

滚动性能演示

这是非常微妙的,但正如你所看到的,当我用鼠标在滚动区域上滚动时,会出现明显的滞后。如果我在非交互式叠加层上滚动,滚动同步是完美的。

但是,我完全不明白为什么会发生这种情况 - 添加叠加层并在其上使用鼠标滚动会提高性能的原因是什么?

标签: javascripthtmlcssgoogle-chromescroll

解决方案


推荐阅读