你如何在rxjs中组合Scheduler.animationFrame和fromEvent(window,' scroll')流?

时间:2017-10-07 14:53:08

标签: javascript rxjs observable requestanimationframe

我有两个可观察者client_id: process.env.PAYPAL_CLIENT_ID!, client_secret: process.env.PAYPAL_CLIENT_SECRET!, & Observable.of(0, animationFrame)。我希望将它们组合起来,以便我的Observable.fromEvent(window, 'scroll')仅在animationFrame的刻度上调用。

renderScrollBar(event)

3 个答案:

答案 0 :(得分:5)

如果您想将滚动事件限制为requestAnimationFrame,则可以使用throttleTime(0, animationFrame)运算符代替Observable.of(0, animationFrame)

实施例

Observable.fromEvent(window, 'scroll')
    .throttleTime(0, animationFrame)

答案 1 :(得分:1)

zip是一个快速而肮脏的解决方案,具有潜在的严重缺陷:当滚动事件发出的速度超过帧速率时,滚动处理程序滞后于真正的滚动值。它看起来像是:

Observable.fromEvent(window, 'scroll')
          .map(event => event.currentTarget)
          .zip(Observable.of(0, animationFrame)
                         .repeat(),
            (currentTarget, _) => this._renderScrollBar(currentTarget)
          );

如果您需要event包含最新的滚动信息,则可能需要使用the window operator更精细的解决方案,例如:

Observable.fromEvent(window, 'scroll')
          .map(event => event.currentTarget)
          .window(Observable.of(0, animationFrame).repeat())
          .mergeMap(w => w.takeLast(1))
          .subscribe(currentTarget => this._renderScrollBar(currentTarget));
  1. 最重要的是,window从源创建一个Observable块流,每次参数Observable发出一个项目时就会进行分块。在这种情况下,每个动画节目都会对一系列滚动事件进行分块。
  2. 如果块不是空的,我们只从每个块中获取最新的,并且mergeMap到平坦的输出流。空块无法为此最终流提供任何项目。

答案 2 :(得分:0)

interval(0)
  .pipe(throttleTime(0, animationFrameScheduler))
  .subscribe(() => {
    fifth++;
  });

scheduled(interval(0), animationFrameScheduler).subscribe(() => {
  sixth++;
});

无论我们将时间设置为 1、2 还是 100 秒,这两个似乎只差 1 帧;)

REAL:  181
FIRST:  109
SECOND:  217
THIRD:  108
FOURTH:  217
FIFTH:  180