2017-01-24 36 views
6

Mục tiêu của tôi là tạo ra một vòng lặp hoạt hình à la requestAnimationFrame để tôi có thể làm điều gì đó như thế này:Làm cách nào để sử dụng RxJS để tạo vòng lặp requestAnimationFrame?

animationObservable.subscribe(() => 
{ 
    // drawing code here 
}); 

Tôi đã thử mã này như một thử nghiệm cơ bản:

let x = 0; 

Rx.Observable 
    .of(0) 
    .repeat(Rx.Scheduler.animationFrame) 
    .takeUntil(Rx.Observable.timer(1000)) 
    .subscribe(() => console.log(x++)); 

Here is a JSFiddle but I'm not liable for any browser crashes from running this.

Tôi mong đợi điều này để ghi lại các số từ 0 đến khoảng 60 (vì đó là tốc độ làm mới của màn hình) trong hơn 1 giây. Thay vào đó, nó nhanh chóng ghi lại các số (nhanh hơn nhiều so với requestAnimationFrame sẽ), bắt đầu làm cho trang bị trễ, và cuối cùng sẽ làm tràn ngăn xếp khoảng 10000 và vài giây sau đó.

Tại sao trình lập lịch biểu animationFrame hoạt động theo cách này và cách chính xác để chạy vòng lặp hoạt ảnh bằng RxJS là gì?

Trả lời

6

Đó là vì hành vi mặc định của Observable.of là phát ra ngay lập tức.

Để thay đổi hành vi này, bạn nên xác định Scheduler khi gọi Observable.of:

let x = 0; 
 

 
Rx.Observable 
 
    .of(0, Rx.Scheduler.animationFrame) 
 
    .repeat() 
 
    .takeUntil(Rx.Observable.timer(1000)) 
 
    .subscribe(() => console.log(x++));
<script src="https://npmcdn.com/@reactivex/[email protected]/dist/global/Rx.min.js"></script>

Hoặc, more simply, thay thế các nhà khai thác ofrepeat với:

Observable.interval(0, Rx.Scheduler.animationFrame) 
+0

Bằng cách nào đó tôi bị mất rằng, có lẽ bởi vì khi tôi lần đầu tiên chạy vào vấn đề tôi đã không sử dụng 'of', nhưng cái gì mà cư xử khác nhau. Đột nhiên nó rõ ràng hơn nhiều. Cảm ơn! –

2

Đây là cách tôi sử dụng reque stAnimationFrame với rxjs. Tôi đã nhìn thấy rất nhiều nhà phát triển sử dụng 0 thay vì animationFrame.now(). Tốt hơn là nên vượt qua thời gian bởi vì bạn thường cần điều đó trong hoạt ảnh.

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)`; 
 
    });
<script src="https://unpkg.com/@reactivex/[email protected]/dist/global/Rx.js"></script> 
 

 
<div style="border: 3px solid black; border-radius: 50%; width: 150px; height: 150px;"> 
 
    <div id="clockPointer" style="width: 2px; height: 50%; background: black; margin-left: 50%; padding-left: -1px; transform-origin: 50% 100%;"></div> 
 
</div>

Các vấn đề liên quan