Efficient design patterns for event handling with RxJS

Oleg Varaksin
2 min readFeb 15, 2018

Programming with RxJS (reactive programming library for JavaScript), TypeScript and Angular is my daily job. RxJS is a new modern way for event handling in cutting-edge web applications. Recently I’ve got a task to implement few interactions on HTML5 canvas element. Exactly these ones:

  • Mousewheel — scroll up / down.
  • Shift + Mousewheel — scroll to the left / to the right.
  • Ctrl + Mousewheel — zoom in / out
  • Panning with mouse (drag and drop the whole canvas)

I’ve done this task with RxJS and would like to share the skeleton of my code with the community. I will only concentrate on the RxJS part and omit complex code with detailed logic. Events can be turned into observable sequence (stream) by the Observable.fromEvent(element, eventName). We are interested in the four events:

  • wheel
  • mousedown
  • mousemove
  • mouseup

We will leverage the following RxJS operators:

  • do— runs a function and is useful when you want to do something for every emission on the source Observable.
  • filter — filters values emitted by the source Observable by the defined predicate function.
  • switchMap — consumes a value from the source Observable, stops emitting values from the source Observable and begins emitting values from the new one (the new Observable is returned from the function passed into the switchMap).
  • share — returns a new Observable that multicasts the source Observable to all subscribers (because of multicasting the stream is “hot”).
  • takeUntil — emits values from the source Observable until a passed in another Observable (typically Subject) emits a value.

For mousewheel interactions, we create a stream of wheel events and share it between specific subscribers. Every subscriber gets filtered events. E.g. for zooming we only interested in wheel events when the Ctrl key is pressed.

For drag and drop, we do a little trick which was the most reliable in my tests. First, three streams from mousedown, mousemove and mouseup are created. The first one is created on the element (here canvas), the last ones are created on the document. As soon as the mouse button is pressed over the element, we switch to the mousemove stream and deliver the difference (delta) of the move positions (mouse movement). The mousemove stream is alive while the mouse button is released. That means, when the mouse button is released, no values (deltas) are delivered to the subscriber.

Have fun! Questions are welcome.

--

--

Oleg Varaksin

Thoughts on software development. Author of “PrimeFaces Cookbook” and “Angular UI Development with PrimeNG”. My old blog: http://ovaraksin.blogspot.de