Javascript 如何在rxjs中组合Scheduler.animationFrame和fromEvent(窗口、滚动和)流?
我有两个可观察的Javascript 如何在rxjs中组合Scheduler.animationFrame和fromEvent(窗口、滚动和)流?,javascript,rxjs,observable,requestanimationframe,Javascript,Rxjs,Observable,Requestanimationframe,我有两个可观察的Observable.of(0,animationFrame)和Observable.fromEvent(窗口“滚动”)。我想将它们组合起来,这样我的renderScrollBar(event)只在animationFrame的刻度上被调用 Observable.fromEvent(window, 'scroll') .map((event: any) => event.currentTarget) .subscribe((event) =>
Observable.of(0,animationFrame)
和Observable.fromEvent(窗口“滚动”)
。我想将它们组合起来,这样我的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++));
}
是一个快速而肮脏的解决方案,它有一个潜在的严重缺陷:当滚动事件发出的速度超过帧速率时,滚动处理程序滞后于真正的滚动值。它看起来像:
Observable.fromEvent(window, 'scroll')
.map(event => event.currentTarget)
.zip(Observable.of(0, animationFrame)
.repeat(),
(currentTarget, _) => this._renderScrollBar(currentTarget)
);
如果您需要event
来包含最新的滚动信息,您可能需要求助于更复杂的解决方案,例如:
window
从源代码创建一个可观察的块流,每次可观察的参数发出一个项时都会进行块。在这种情况下,一系列滚动事件由每个动画标记分块如果要将滚动事件限制到requestAnimationFrame,可以使用
throttleTime(0,animationFrame)
操作符,而不是Observable.of(0,animationFrame)
范例
Observable.fromEvent(window, 'scroll')
.throttleTime(0, animationFrame)
更新:
RxJS 6
import { fromEvent, animationFrameScheduler } from "rxjs";
import { throttleTime } from "rxjs/operators";
fromEvent(window, "scroll")
.pipe(throttleTime(0, animationFrameScheduler))
无论我们设定的时间是1秒、2秒还是100秒,这两个似乎只差1帧;)
我不认为有任何简单的方法可以在RxJS中的每个动画帧上运行动作。你想要的是行为吗?@concat我想是的,你能在答案中制作一个示例吗?我会尝试一下,并将其标记为正确。它似乎正常工作,但我得到一个错误EmptyError{name:“EmptyError”,stack:“EmptyError:序列中没有元素,message:“序列中没有元素”}message:“序列中没有元素”name:“EmptyError”stack:“EmptyError:序列中没有元素”sequence@MatthewHarwood我的坏,
takeLast(1)
是您想要的,因为它不会抛出空流。我建议将其更新到RXJS 6,但回答很好。这个答案帮助我最终修复了一个困扰我们几个月、几乎无法追踪的错误!非常感谢。我们将throttleTime
操作符放在更下游的位置,而不是正好在fromEvent
之后,不知何故,这把事情搞砸了。如果您对沉默时间窗口中的最新事件感兴趣,而不是第一个事件,然后我建议使用auditTime
操作符,而不是throttleTime
。
import { fromEvent, animationFrameScheduler } from "rxjs";
import { throttleTime } from "rxjs/operators";
fromEvent(window, "scroll")
.pipe(throttleTime(0, animationFrameScheduler))
interval(0)
.pipe(throttleTime(0, animationFrameScheduler))
.subscribe(() => {
fifth++;
});
scheduled(interval(0), animationFrameScheduler).subscribe(() => {
sixth++;
});
REAL: 181
FIRST: 109
SECOND: 217
THIRD: 108
FOURTH: 217
FIFTH: 180