I'm creating a thread to control mouse directions (pixel by pixel) using javascript. Sometimes I need to stop the mouse movement and give it a new direction (a set of pixels). I would like to use Observables.
I would like to output the pixel sequences, for example: [(x0, x0), ..., (xN, yN), (x1, y1)]
If a new set of pixels is issued, the previous one will be cleaned.
I would like to know the best way to do this, which operators, etc.
CodePudding user response:
Assuming you are emitting a "sequence" as an array of "points", something like this should work:
type Point = [number, number];
const DELAY = 200;
const pixelSequence$ = new Subject<Point[]>();
const mousePoint$ = pixelSequence$.pipe(
switchMap(sequence => timer(0, DELAY).pipe(
map(i => sequence[i]),
take(sequence.length),
))
);
mousePoint$.subscribe(
([x, y]) => setMousePosition(x, y)
);
Here we start with a Subject that will emit a "pixel sequence" (Point[]
). We can define a new Observable that will emit individual points, then subscribe to that observable to set the cursor position:
mousePoint$.subscribe(
([x, y]) => setMousePosition(x, y)
);
The core of the functionality happens in the definition of mousePoint$
. We define a new Observable that begins when pixelSequence$
emits a value. We then use switchMap
and create an "inner observable" that emits the sequence items one at a time at with the specified DELAY inbetween.
switchMap(sequence => timer(0, DELAY).pipe(
map(i => sequence[i]),
take(sequence.length),
))
If you aren't familiar with switchMap
, it basically receives a emission as input, then subscribes to an "inner observable" for you, emitting its emissions. When switchMap
receives a new emission, it will "switch" its inner source to a new observable, unsubscribing from its previous "inner observable".
So, to begin your mouse moving, simply call pixelSequence$.next()
with an array of coorinates. If you need to use a different sequence (whether or not the current sequence has been fully processed), simply call pixelSequence$.next()
again with the new sequence.
Here is a example on StackBlitz.
Operators used:
switchMap
- subscribe to inner observable and emit its emissionstimer
- emit sequential integers at the specified intervalmap
- transform each emission with the provided functiontake
- complete the observable when the specified number of emissions have been received