我有两个可观测量Observable.of(0, animationFrame)
和Observable.fromEvent(window, 'scroll')
。我想把它们组合起来,这样我的renderScrollBar(event)
只在animationFrame的滴答声中被调用。
Observable.fromEvent(window, 'scroll')
.map((event: any) => event.currentTarget)
.subscribe((event) => {
this._renderScrollBar(event);
});
let x = 0;
Observable.of(0, animationFrame)
.repeat()
.takeUntil(Observable.timer(1000))
.subscribe(() => console.log(x++));
}
4条答案
按热度按时间2fjabf4q1#
如果你想将scroll事件限制为requestAnimationFrame,你可以使用
throttleTime(0, animationFrame)
操作符而不是Observable.of(0, animationFrame)
。示例
更新:
RxJS 6
a0x5cqrl2#
zip
是一个快速而肮脏的解决方案,它有一个潜在的严重缺陷:当滚动事件比帧速率更快地发出时,滚动处理程序滞后于真实滚动值。它看起来像这样:如果你需要
event
来包含最新的滚动信息,你可能需要使用window
操作符来解决这个问题,比如:1.最重要的是,
window
从源创建一个Observable块流,每次参数Observable发出一个项目时,都会分块。在这种情况下,一系列滚动事件按每个动画节拍分块。1.如果每个块不是空的,我们只从每个块中提取最新的,然后将其
mergeMap
到一个平面输出流。空块不会为最终流贡献任何项目。sycxhyv73#
无论我们设定的时间是1秒、2秒还是100秒,这两个似乎都只差1帧;)
7cwmlq894#
相信浏览器!
我在一个全局服务中使用以下代码的时间最长:
决定做一些测试,看看是否可以通过使用animationFrame来提高性能(并不是说我有任何已知的问题)。
结果:
在我的桌面版Chrome和iOS版Safari的测试中,我找不到任何方法通过添加animationFrame调度来改进上述功能。
方法:
创建上述可观察值的第二个变体,将
throttleTime
与animationFrameScheduler
相加。然后订阅两者,看看哪个先达到100个排放量。我总是得到
v1=100, v2=100
,证明它们在发射计数方面是相同的。总结
浏览器已经只在值发生变化时才会发出scroll事件。它不会比动画帧更频繁地这样做-为什么会这样?那样做是没有意义的。
如何处理:
为了提高性能,你可以做的第一件事就是把你的可观察对象放在一个全局(
providedIn: 'root'
)服务中(注意shareReplay
)。然后,无论何时使用它,您都将引用同一个示例并仅创建一个浏览器事件。忘记所有关于animationFrame调度器的东西。顺便说一句:
distinctUntilChanged()
在这里只是为了忽略水平滚动(因为y值保持不变,但仍然会得到事件)。如果你没有水平滚动条,你永远不会注意到差异。如果您实际上要执行一个复杂的操作,那么根据您的具体需要使用
throttleTime
或debounceTime
。AnimationFrame在这里不会帮助您。