Scroll-linked effects

这篇翻译不完整。请帮忙从英语翻译这篇文章

scroll-linked效果指的是某种因滚动条位置变化的而产生的效果,例如,为了产生视差滚动效果而更新position属性。 本文讨论scroll-linked效果,这些效果对性能的影响,相关工具以及可以缓解的技术。

滚动效果解释

滚动效果一般是指通过监听scroll事件,并以某种方式修改页面上的元素(通常是CSS的positiontransform属性)你可以在《CSS Scroll API: Use Cases》找到这样的效果

当滚动在浏览器主线程上完成时,这些效果运行良好。但是,大多数浏览器现在支持一种异步滚动,以便为用户提供恒定每秒60帧的体验。在异步滚动模型中,视觉滚动位置(译者注:即用户看到的滚动位置)在合成器线程中更新,并在DOM更新scroll事件、主线程触发scroll事件之前对用户可见。这意味着实际显示的效果将会落后于用户看到的滚动位置一点点。 这可能会导致效果变得迟缓,总之,我们想要避免这种情况。

下面是一些在异步滚动中不能良好运行的例子,以及可以很好地运行的等效版本:

 
 
 

示例1:粘性定位

这是一个粘性定位效果的实现,其中“toolbar”的div将在您向下滚动时“粘”在屏幕顶部

 
 
<body style="height: 5000px" onscroll="document.getElementById('toolbar').style.top = Math.max(100, window.scrollY) + 'px'">
 <div id="toolbar" style="position: absolute; top: 100px; width: 100px; height: 20px; background-color: green"></div>
</body>

Instead, it will move with the user's scrolling, and then "snap" back into position when the scroll event handler runs. This constant moving and snapping will result in a jittery visual effect. One way to implement this without the scroll event listener is to use the CSS property designed for this purpose:

这种粘性定位的实现依赖于监听滚动事件,来重新定位toolbar”的div。由于滚动事件监听器运行于浏览器主线程的JavaScript中,它与用户可见的滚动是异步的。所以,因为有异步滚动,事件处理程序将相对于用户可见的滚动来说是有延迟的,这个div不会像预期那样保持视觉上的固定。相反,它将随用户的滚动移动,然后在滚动事件处理器运行时突然回到应有的位置。这种恒定的移动和捕捉将会导致视觉效果的抖动。其中一种解决方法是使用为此设计的CSS属性,而不是用滚动事件监听器:

 
 
<body style="height: 5000px">
 <div id="toolbar" style="position: sticky; top: 0px; margin-top: 100px; width: 100px; height: 20px; background-color: green"></div>
</body>

此版本适用于异步滚动,当用户滚动时,浏览器会更新“toolbar”的div的位置。

 
 

示例2:滚动捕捉

 
 

此功能已从Web标准中删除。 虽然一些浏览器可能仍然支持它,但它正在被放弃。尽量不要使用它,并尽可能更新现有代码。https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-coordinate#Browser_compatibility

 

where the scroll position snaps to a particular destination when the user's scrolling stops near that destination.

以下是滚动捕捉的实现,当用户的滚动停止在snaptarget附近时,滚动位置捕捉到特定目的地(snaptarget)。

 
 
<body style="height: 5000px">
 <script>
    function snap(destination) {
        if (Math.abs(destination - window.scrollY) < 3) {
            scrollTo(window.scrollX, destination);
        } else if (Math.abs(destination - window.scrollY) < 200) {
            scrollTo(window.scrollX, window.scrollY + ((destination - window.scrollY) / 2));
            setTimeout(snap, 20, destination);
        }
    }
    var timeoutId = null;
    addEventListener("scroll", function() {
        if (timeoutId) clearTimeout(timeoutId);
        timeoutId = setTimeout(snap, 200, parseInt(document.getElementById('snaptarget').style.top));
    }, true);
 </script>
 <div id="snaptarget" style="position: relative; top: 200px; width: 100%; height: 200px; background-color: green"></div>
</body>

在该示例中,有滚动事件监听器,其检测滚动位置是否在“snaptarget”的div顶部的200像素内。 如果是,则触发动画将div的顶部“卡”到滚动位置。 由于此动画由浏览器主线程上的JavaScript驱动,所以可以被其他选项卡或其他窗口中运行的JavaScript中断。 因此,动画可能最终看起来很漂亮,但并不像预期那样平滑。 相反,使用CSS的snap-points属性将允许浏览器异步运行动画,为用户提供平滑的视觉效果。

 
<body style="height: 5000px">
 <style>
    body {
        scroll-snap-type: proximity;
        scroll-snap-destination: 0 0;
    }
    #snaptarget {
        scroll-snap-coordinate: 0 -8px;
    }
 </style>
 <div id="snaptarget" style="position: relative; top: 200px; width: 100%; height: 200px; background-color: green"></div>
</body>

即使浏览器的主线程中运行的JavaScript速度较慢,该版本也能在浏览器中顺利运行。

 
 

其他效果

In many cases, scroll-linked effects can be reimplemented using CSS and made to run on the compositor thread. However, in some cases the current APIs offered by the browser do not allow this. In all cases, however, Firefox will display a warning to the developer console (starting in version 46) if it detects the presence of a scroll-linked effect on a page. Pages that use scrolling effects without listening for scroll events in JavaScript will not get this warning. See the Asynchronous scrolling in Firefox blog post for some more examples of effects that can be implemented using CSS to avoid jank.

在不少情况下,scroll-linked 效果能够通过css和在排序线程运行来重新实现。 然而, 有时浏览器提供的API不允许这么做。但是不管怎样, 如果Firefox(从第46个版本之后)检测到页面上的scroll-linked效果, 将在控制台向开发人员显示警告 。 需要说明的是,使用滚动效果的页面如果在JavaScript中不监听滚动事件将无法获得此警告。你可以看此博客文章( Asynchronous scrolling in Firefox )来了解更多通过css来实现避免页面延迟的例子。

未来改进

Going forward, we would like to support more effects in the compositor. In order to do so, we need you (yes, you!) to tell us more about the kinds of scroll-linked effects you are trying to implement, so that we can find good ways to support them in the compositor. Currently there are a few proposals for APIs that would allow such effects, and they all have their advantages and disadvantages. The proposals currently under consideration are:

未来我们将在compositor中支持更多的效果。为了完成这个目标,我们需要你(没错,就是你!)来告诉我们更多的你努力实现的scroll-linked效果,以便我们可以找到好的方式来支持它们。目前有几个对于API的提案可以实现这种效果,它们也都有各自的优缺点。目前正在审议的提案是:

  • Web Animations: A new API for precisely controlling web animations in JavaScript, with an additional proposal to map scroll position to time and use that as a timeline for the animation.
  • Web Animations:在JavaScript中新增一个API,用于精确控制Web动画,还有一个额外提议——将滚动位置映射到时间,并将其用作动画的时间轴。
  • CompositorWorker: Allows JavaScript to be run on the compositor thread in small chunks, provided it doesn't cause the framerate to drop.
  • CompositorWorker: 允许JavaScript在小块中的合成器线程上运行,前提是不会导致帧率下降
  • Scroll Customization: Introduces a new API for content to dictate how a scroll delta is applied and consumed. As of this writing, Mozilla does not plan to support this proposal, but it is included for completeness.
  • Scroll Customization: 引入一个新的内容API来决定如何应用和消费滚动增量。在撰写本文时,Mozilla并不打算支持这个提议,但是为了完整性,它被包括在内。

Call to action

If you have thoughts or opinions on:

  • Any of the above proposals in the context of scroll-linked effects.
  • Scroll-linked effects you are trying to implement.
  • Any other related issues or ideas.

Please get in touch with us! You can join the discussion on the public-houdini mailing list.

 

生成短网址生成短网址

 

文档标签和贡献者

此页面的贡献者: yuin2018, shuangya
最后编辑者: yuin2018,