“此站点似乎使用滚动链接定位效果。这可能不适用于异步平移”

IT技术 javascript jquery firefox
2021-02-25 07:57:11

我收到了来自 Firefox 的这个不寻常的警告。它所指的定位效果是一个divI 旋转作为滚动高度的一个因素。我从来没有遇到过任何问题,但这是我应该担心的事情吗?无论如何,如果没有这个警告,会有这样的影响吗?演示此问题的 JavaScript 是:

$('.gear').css({
   'transition': 'transform 1s ease-out',
   '-webkit-transform': 'rotate(' + Math.round(wScroll / 2) + 'deg)',
   '-moz-transform': 'rotate(' + Math.round(wScroll / 2) + 'deg)',
   '-ms-transform': 'rotate(' + Math.round(wScroll / 2) + 'deg)',
   'transform': 'rotate(' + Math.round(wScroll / 2) + 'deg)',
});
  • wScroll 是当前滚动高度
3个回答

我认为,警告继续说:

...请参阅https://developer.mozilla.org/docs/Mozilla/Performance/ScrollLinkedEffects了解更多详情并加入相关工具和功能的讨论!

2021 年更新:文档已移至https://firefox-source-docs.mozilla.org/performance/scroll-linked_effects.html

但如果该页面不清楚,这里是它的要点。

“异步平移”的想法是这样的:当页面滚动时,浏览器调用您的scroll处理程序,但它也会在新的滚动点异步绘制页面。这样做是为了使滚动显示响应(@ 60 FPS),即使主线程繁忙超过 16 毫秒。

这意味着您的处理程序实现的效果不能保证与当前滚动位置同步。即滚动是平滑的,但是您的 div 以较小的 FPS 旋转 - 出现卡顿、不流畅。 更新transition在您的示例中错过了效果——旋转本身也将是平滑的,但它可能会晚于页面开始滚动。

我不认为你可以在没有这个问题的情况下实现你使用当前可用技术的确切效果。

例子

(请注意,要查看APZ 的运行情况,您需要在启用它的情况下运行 Firefox 版本。特别是这需要 Firefox 以多进程(“e10s”)模式运行,该模式目前仍未在发布版本中时间。)

window.onscroll = function() {
  var wScroll = document.documentElement.scrollTop;
  document.getElementById("gear-css").style.transform = 'rotate(' + Math.round(wScroll / 2) + 'deg)';
  document.getElementById("gear-js") .style.transform = 'rotate(' + Math.round(wScroll / 2) + 'deg)';
  document.getElementById("gear-js").textContent = leftPad(wScroll+'', '0', 4);

  setTimeout(slowdown(500), 0);
};

function leftPad(s, ch, maxLen) { return ch.repeat(maxLen - s.length) + s; }
function slowdown(timeMs) {
  return function() {
    var start = Date.now();
    var j = "";
    for (var i = 0; (Date.now() - start < timeMs); i++)
      j = j+(start+"")*i;
  }
}


window.onload = function() {
  for (let i = 0; i < 15; i++) {
    var p = document.createElement("p");
    p.innerText = `Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
          tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
          quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
          consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
          cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
          proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`;
    document.documentElement.appendChild(p);
  }
}
#gear-css, #gear-js {
  border: solid black 1px;
}
#gear-css {
  transition: transform 1s ease-out
}
<div style="position: fixed; top: 0; right: 0; padding: 3em;">
  <div id="gear-css">ooo</div>
  <div id="gear-js">ooo</div>
</div>

@MarcelWaldvogel 感谢您提醒我更新firefox-source-docs.mozilla.org/performance /...的链接——它也将在 Firefox 92 中更新
2021-04-19 07:57:11
谢谢你 Nickolay,正如你所说的页面不是很清楚,但你肯定有帮助!
2021-04-20 07:57:11
Firefox 仍然引用他们的 docs/Mozilla/Performance/ScrollLinkedEffects 页面,但它不再存在。所以我们需要一个脱离 MDN 的描述,我们这里有。
2021-04-21 07:57:11
@MichaelHancock:请注意,MDN 是一个 wiki,所以如果您有关于如何使页面对没有构建浏览器的人更清晰的建议,我们非常欢迎。我记得他们遇到过垃圾邮件发送者的问题,所以创建一个新帐户可能比它更难,但无论如何,如果您有兴趣提供帮助,请与我们联系
2021-05-04 07:57:11

我知道这个问题是前一段时间被问到的,但是,性能问题仍然存在。以下是不依赖滚动事件侦听器的替代解决方案。这最大限度地减少了由 Web 浏览器中常见的单独滚动线程引起的卡顿和延迟,定期更新 css,而不是在滚动窗口时。这意味着不会显示开发控制台警告。我个人不会太担心警告或使用滚动事件来处理诸如转动齿轮或更改css类之类的小事情,但是,如果用户体验直接依赖于效果,则会破坏页面的可用性。

var gear;
var lastPosition;
var refreshRate = 60; // fps; reduce for less overhead
var animation = "rotate(*deg)"; // css style to apply [Wildcard is *]
var link = 0.5; //what to multiply the scrollTop by

function replace(){
    if(lastPosition != document.body.scrollTop){ // Prevents unnecessary recursion
        lastPosition = document.body.scrollTop; // updates the last position to current
        gear.style.transform = animation.replace("*", Math.round(lastPosition * link)); // applies new style to the gear
    }
}

function setup(){
    lastPosition = document.body.scrollTop;
    gear = document.querySelector(".gear");
    setInterval(replace, 1000 / refreshRate); // 1000 / 60 = 16.666... Invokes function "replace" to update for each frame
}
window.addEventListener("DOMContentLoaded", setup);

可以在我的 GitHub 上使用一个工作示例我已经在 Firefox、Chrome 和 Edge(有效)上对其进行了测试。

避免警告的其他替代方法是使用css 粘性元素或使用与window.onscroll事件相关联element.classList.add()element.classList.remove()方法

注意:使用 css 转换时要小心,如果转换的长度大于脚本更新 CSS 样式的间隔(例如基于滚动事件的更改)。基于 Webkit 的浏览器和 EdgeHTML 会以意想不到的方式运行,通常会停留在它们的初始位置,直到元素停止被脚本更新。除非这是您想要的效果,在这种情况下,它在 Firefox 中的工作方式不同。

Servo Webrender 集成到 Firefox 后将在一定程度上解决这些问题(或者至少可以相当大地提高性能)。虽然仍然会有其他浏览器来保持兼容性。

您的回答并没有解决问题,只是抑制了消息。此外,使用轮询(您这样做)而不是基于事件的回调对 CPU 使用率、热量和电池不利。正是出于这个原因,浏览器不赞成setInterval并链接setTimeout.
2021-04-27 07:57:11

最好的解决方案是一个开关和一个计时器,我在这里公开了解决相同错误的答案,当您使用“滚动”时,我建议您根据自己的需要调整我的脚本! https://stackoverflow.com/a/57641938/5781320