我的目标是创建一个动画循环,requestAnimationFrame
以便我可以这样做:
animationObservable.subscribe(() => { // drawing code here });
我尝试将此代码作为基本测试:
let x = 0; Rx.Observable .of(0) .repeat(Rx.Scheduler.animationFrame) .takeUntil(Rx.Observable.timer(1000)) .subscribe(() => console.log(x++));
这是一个JSFiddle,但我不负责任何浏览器崩溃运行它.
我希望这会将数字从0记录到大约60(因为这是我的显示器的刷新率)超过1秒.相反,它会快速记录数字(比它快得多requestAnimationFrame
),开始导致页面滞后,最后在10000和几秒钟后溢出堆栈.
为什么animationFrame
调度程序以这种方式运行,使用RxJS运行动画循环的正确方法是什么?
这是因为默认行为Observable.of
是立即发出.
要更改此行为,您应指定Scheduler
何时调用Observable.of
:
let x = 0;
Rx.Observable
.of(0, Rx.Scheduler.animationFrame)
.repeat()
.takeUntil(Rx.Observable.timer(1000))
.subscribe(() => console.log(x++));
这就是我将requestAnimationFrame与rxjs一起使用的方法.我见过很多开发人员使用0而不是animationFrame.now().通过时间会好得多,因为你经常需要动画.
const { Observable, Scheduler } = Rx;
const requestAnimationFrame$ = Observable
.defer(() => Observable
.of(Scheduler.animationFrame.now(), Scheduler.animationFrame)
.repeat()
.map(start => Scheduler.animationFrame.now() - start)
);
// Example usage
const duration$ = duration => requestAnimationFrame$
.map(time => time / duration)
.takeWhile(progress => progress < 1)
.concat([1])
duration$(60000)
.subscribe((i) => {
clockPointer.style.transform = `rotate(${i * 360}deg)`;
});