2017-10-07 3 views
0

J'ai deux observables Observable.of(0, animationFrame) & Observable.fromEvent(window, 'scroll'). Je veux les combiner pour que mon renderScrollBar(event) ne soit appelé que sur les ticks d'animationFrame.Comment combinez-vous Scheduler.animationFrame et fromEvent (fenêtre, 'scroll') dans rxjs?

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++)); 
} 
+0

Je ne pense pas qu'il y ait un moyen facile d'exécuter une action sur tous les animationFrame en RxJS. – martin

+0

Is [zip] (http://reactivex.io/documentation/operators/zip.html) le comportement que vous recherchez? – concat

+0

@concat Je pense que vous seriez en mesure de faire un échantillon dans la réponse? Je vais l'essayer et le marquer correctement –

Répondre

3

Si vous voulez accélérateur événement de défilement pour requestAnimationFrame vous pouvez utiliser throttleTime(0, animationFrame) opérateur au lieu de Observable.of(0, animationFrame).

Exemple

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

zip est une solution rapide et sale qui a un défaut potentiellement grave: le gestionnaire de défilement est en retard sur la valeur réelle de défilement lorsque des événements de défilement émettent plus vite que la vitesse de défilement. Il ressemblerait à quelque chose comme:

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

Si vous avez besoin event pour contenir les dernières informations de défilement, vous pourriez avoir besoin de recourir à une solution plus élaborée avec the window operator, comme:

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. Foremost , window crée un flux de morceaux Observable à partir de la source, fragmenté chaque fois que l'argument Observable émet un élément. Dans ce cas, des séries d'événements de défilement sont tronquées par chaque tique d'animation.
  2. Nous prenons seulement les plus récents de chaque morceau si le morceau n'est pas vide, et mergeMap cela à un flux de sortie plat. Les morceaux vides ne contribueront aucun élément à ce dernier flux.
+0

il semble fonctionner mais j'obtiens une erreur EmptyError {name: "EmptyError", pile: "EmptyError: aucun élément dans la séquence, message:" no elements in sequence " } un message : "aucun élément dans l'ordre" nom : "EmptyError" pile : « EmptyError: pas d'éléments dans l'ordre –

+0

@MatthewHarwood Mon mauvais,' takeLast (1) 'est ce que vous voulez, comme ne jettera pas sur les flux vides. – concat