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

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

 //Rotate gears in about section $('.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是当前的滚动高度

我想,警告继续说:

…有关详细信息,请参阅https://developer.mozilla.org/docs/Mozilla/Performance/ScrollLinkedEffects ,并加入有关相关工具和function的讨论!

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

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

这意味着您的处理程序实现的效果不能保证与当前滚动位置同步。 即滚动顺畅,但是 你的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 } 
 
ooo
ooo

我知道这个问题是前一段时间被问到的,然而,性能问题仍然存在。 下面是一个不依赖于滚动事件监听器的替代解决方案。 这最大限度地减少了由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中的工作方式不同。

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