1.3.6 • Published 1 year ago

@rgrueneis/rxjs-visualizer v1.3.6

Weekly downloads
19
License
ISC
Repository
-
Last release
1 year ago

RxJsVisualizer

This plugin is intended to illustrate streaming with RxJs. For this purpose, the resulting values/objects are displayed on a timeline by making special observer objects available.
symbol_screenshot
You can configure whether the elements are displayed as graphic symbols or as texts/values.
text_screenshot

List of features

  • Display values of observables on various timeplines
  • Operator draw to be used within a pipe
  • Various generation functions
  • UMD module that can be used in plain Javascript as well as in Angular/Ionic

Download & Installation

node
$ npm i @rgrueneis/rxjs-visualizer 
yarn
$ yarn add @rgrueneis/rxjs-visualizer 

Usage Plain HTML

To use RxVis the following is required:

  • RxJs 7.x
  • rxjs.visualizer.min.js
  • a <canvas>-Element
  • optionally a <div> for displaying the logs

A minimal setup could look like this:

HTML
<html>
<head>
  <meta charset="UTF-8" />
  <title>Hello RxJs</title>
  <!-- <script src="https://unpkg.com/rxjs/bundles/rxjs.umd.min.js"></script>  -->
  <script src="node_modules/rxjs/dist/bundles/rxjs.umd.min.js"></script>
  <script src="node_modules/@rgrueneis/rxjs-visualizer/rxjs.visualizer.umd.min.js"></script>
  <script src="index.js"></script>
  <link rel="stylesheet" type="text/css" href="index.css">
</head>
<body>
  <canvas id="canvas" width="700" height="300"></canvas>
  <div id="logs">Output comes here</div>
</body>
</html>
Javscript
window.onload = () => {
  RxJsVisualizer.init({
    canvasId: 'canvas',
    logDivId: 'logs'
  });

  RxJsVisualizer.prepareCanvas(['values']);
  RxJsVisualizer.startVisualize();
  RxJsVisualizer.createStreamFromArraySequence([10, 11, 12, 13, 14])
    .subscribe(RxJsVisualizer.observerForLine(0, 'value', true));
};
CSS
.clock {
  color: blue;
}
.msg, .error {
  margin-left: 1em;
}
.error {
  color: red;
}
.completed {
  color: green;
}
#logs {
  margin-top: 1em;
  font-family: 'Courier New', Courier, monospace;
  font-size: 0.75em;
}
#canvas {
  background-color: lightblue;
}
References Plain Javascript

The following references have to be added to a Javascript file to be able to use RxJs visualization:

  const { DrawingSymbol } = RxJsVisualizer;
  const { draw } = RxJsVisualizer.operators;

Angular/Ionic

For Angular or Ionic a <canvas> tag has to be positioned, usually in app.component.html:

<router-outlet></router-outlet>
<canvas id="canvas" width="680" height="150"
        style="background-color:skyblue;z-index: 999;position: absolute;bottom: 55px;"></canvas>
References Angular/Ionic

The following imports have to be added to app.component.ts:

import { init,  draw, prepareCanvas, startVisualize } from '@rgrueneis/rxjs-visualizer';

Core concepts

The following chapters show the core concepts of RxJsVisualizer. They are shown for plain Javascript. Next to that chapter the code snippet for Angular/Ionic is shown.

init

Before using RxJsVisualizer the RxVis-object has to be initialized. This is done with an options object, which in the minimal version looks like this.

RxJsVisualizer.init({
    canvasId: 'canvas',
    logDivId: 'logs'
});

The Ids correspond to the Ids of a <canvas> and a <div>, respectively, given in the HTML file.

startVisualize

To start the visual animation the function startVisualize() has to be called. This will clear the canvas and (re)start the timer.

RxJsVisualizer.prepareCanvas(['values']);
RxJsVisualizer.startVisualize();
RxJsVisualizer.createStreamFromArraySequence([10, 11, 12, 13, 14])
    .subscribe(RxJsVisualizer.observerForLine(0, 'value', true));
Observer

Two functions are required:

  • prepareCanvas: the array given as parameter specifies the number and headings of the various timelines
  • observerForLine: specifies the line index, where the objects of the stream are written/drawn.
RxJsVisualizer.prepareCanvas(['Val']);
RxJsVisualizer.startVisualize();
Rx.timer(1000, 2000)
      .pipe(take(3))
      .subscribe(RxJsVisualizer.observerForLine(0));

This will result in the following output:
observer_screenshot

pipeable operator draw

Another possibility to draw to the timeline is using the pipeable operator draw.
Example:

RxJsVisualizer.prepareCanvas(['values', 'times10']);
RxJsVisualizer.startVisualize();
RxJsVisualizer.createStreamFromArraySequence([10, 11, 12, 13, 14])
    .pipe(
        draw(0, '', true),
        map(x => x * 10)
    )
    .subscribe(RxJsVisualizer.observerForLine(1, '*10:', true));

Result:
draw_screenshot

Angular/Ionic

For Angular/Ionic the init routine is best placed in app.component.ts at the end of ngOnInit():

init({
  canvasId: 'canvas',
  blockHeight: 50,
  shapeSize: 20,
  autoExpandCanvasWidth: false
});
prepareCanvas(['A', 'B', 'C']);
startVisualize();
// next lines for testing:
// prepareCanvas(['values', 'times10']);
// createStreamFromArraySequence([10, 11, 12, 13, 14])
//   .pipe(
//     draw(0, '', true),
//     map(x => x*10)
//   )
//   .subscribe(observerForLine(1, '*10:', true));

Symbols

Instead of writing text to the timeline it is often more vivid to display symbols instead. To do so, for any text a symbol can be registered (details to class DrawingSymbolsee below).

const symbols = {};
symbols['[object MouseEvent]'] = new DrawingSymbol({ color: 'blue', shape: 'circle' });
symbols['0'] = new DrawingSymbol({color:  'white', shape:'circle'});
symbols['1'] = new DrawingSymbol({color:  'black', shape:'square'});
symbols['2'] = new DrawingSymbol({color:  'red', shape:'triangle'});
RxJsVisualizer.init({
    canvasId: 'canvas',
    logDivId: 'logs',
    symbolMap: symbols
});
RxJsVisualizer.useRandomSymbolsForNumbers(100);

With these symbols the above RxJs-stream will be displayed like this:
symbol-example_screenshot

useRandomSymbolsForNumber

As marble diagrams are used quite often, a helper function is available to generate standard symbols for numbers. The following code generates symbols for all numbers 0-99:

RxJsVisualizer.useRandomSymbolsForNumbers(100);

API

The plugin essentially consists of the object RxJsVisualizer. Various shape objects are registered in the class ShapeFactory, which is not accessible to the user. Any of the registered shapes can be used by creating and mapping an instance of class DrawingSymbol to a text. The elapsed time is indicated as a growing orange line below the last timeline.

Shapes

The following shapes are available:
shapes-overview_screenshot

RxJsVisualizer

This class is responsible for drawing objects to the timeline. The number of timelines can configured by the user. The general setup is configured with the init method.

init

Before using any other functions of RxVis this method has to be called once. The only parameter is an options object with the following properties.

keytypeDefaultdescription
headerWidthnumber50Number of pixels used for the header on each line
marginHorizontalnumber5Margin in pixels left and right
marginVerticalnumber40Margin top and bottom in pixels.
blockHeightnumber50Height of a timline-block in pixels.
shapeSizenumber20Size of a shape symbol in pixels
centerShapesbooleanfalseSpecifies if the shapes are drawn centered on the time tick or next (=right) to the timetick.
autoExpandCanvasWidthbooleanfalseIf true, stretches the canvas width so that the whole browser window is used horizontally.
Fontstring'italic 12px sans-serif'With this font any text is drawn to the timeline.
guidelineColorstring'gray'Color of the guideline (the dotted line down to the last timeline)
tickColorstring'black'Color of the ticks
colorsarray'white', 'black', 'red', 'blue', 'green', 'cyan', 'violet', 'yellow', 'darkgray'The standard colors used when generating random symbols.
canvasIdstring'canvas'Id of the -Element. Here the visualization is displayed.
logDivIdstring'logs'Id of the -Element that should show the logs.
maxPeriodnumber10000Maximum period of the timeline milliseconds.
tickPeriodnumber1000Number of milliseconds when a timestamp is drawn.
symbolMapobject{}Map that defines, which text should be replaced by which symbol. Format: {string:DrawingSymbol}
guidelineColorstring'gray'Color of the dotted vertical guidelines
showTimeTicksbooleantrueIndicates if a time tick is drawn every second to the timeline
tickColorstring'black'Color of the ticks on the timelines.
addNavigationButtonsbooleanfalseAdd buttons to the canvas to be able to stop scrolling and navigate back and forth navigation_screenshot
maxLogLengthnumber-1used to limit the output strings in the log div (<=0) ==> do not lmit

Example:

RxJsVisualizer.init({
    canvasId: 'canvas',
    logDivId: 'logs',
    blockHeight: 50,
    shapeSize: 20,
    centerShapes: false,
    symbolMap: { 
      '[object MouseEvent]': new DrawingSymbol({ color: 'blue', shape: 'circle' }) 
    }
});
prepareCanvas

This method specifies the number of lines and the headers shown for each line. |parameter |type |Default |description| | --------------------- |:---------:|:---------:| --------- | |headerNames |array |'A','B' |Number names of the header of each line|

Example:

RxJsVisualizer.prepareCanvas(['A', 'B']);
observerForLine

With this function an observer is created for a given timeline. All next, error or complete values are then drawn at the timeline. |parameter |type |Default |description| | --------------------- |:---------:|:---------:|:--------- | |lineNr |number |- |Number of the timeline where this observer shall draw its values (zero-based).| |header |string |'' |This header is only used for the log output to identify the source of the output. For the graphical display this value is ignored.| |shouldIgnoreSymbols |boolean |false |If set to true, no symbols are used for this timeline, no matter if there is a symbol defined for the text or not.| |valueMapper |function |- |If set, this function is called for each value before it is written/drawn to the timeline. Example: observerForLine(0, 'name', false, x => x.substr(0, 2))

It has to be imported from RxJsVIsualizer.operators.
Example:

RxJsVisualizer.prepareCanvas(['Val']);
RxJsVisualizer.startVisualize();
Rx.timer(1000, 2000)
  .pipe(take(3))
  .subscribe(RxJsVisualizer.observerForLine(0));
startVisualize

When starting a new RxJs stream, this method has to be called before. It clears the display as well as the logs and starts the timer.
Example:

RxJsVisualizer.prepareCanvas(['Val']);
RxJsVisualizer.startVisualize();
Rx.timer(1000, 2000)
  .pipe(take(3))
  .subscribe(RxJsVisualizer.observerForLine(0));
useRandomSymbolsForNumbers

As often numbers are produced for RxJs demos with this function random symbols are generated for a range of numbers. So the symbolMap is automatically extended for the given numbers. |parameter |type |Default |description| | --------------------- |:---------:|:---------:|:--------- | |maxNr |number |100 |Numbers 0..maxNr are mapped to random colored symbols.

Example:

RxJsVisualizer.useRandomSymbolsForNumbers(100);
writeToLine

Some additional text can be drawn at the current time-position to the given timeline. It will be shown below the timeline. |parameter |type |Default |description| | --------------------- |:---------:|:---------:|:--------- | |lineNr |number |- |Numbers of the timeline |Text |string |- |String to be written to the timeline.

Example:

RxJsVisualizer.prepareCanvas(['produce', 'A', 'B']);
const observable = Rx.interval(1000).pipe(take(3));
observable.subscribe(RxJsVisualizer.observerForLine(0, 'produce'));
const connectable = observable.pipe(publish());
RxJsVisualizer.writeToLine(1, 'Subscribing now A');
connectable.subscribe(RxJsVisualizer.observerForLine(1, 'subscriber A'));
RxJsVisualizer.writeToLine(2, 'Subscribing now B');
connectable.subscribe(RxJsVisualizer.observerForLine(2, 'subscriber B'));
setTimeout(_ => {
    RxJsVisualizer.writeToLine(0, 'Connect');
    connectable.connect();
}, 2500);
rnd

Helper function to create random numbers in a given range. |parameter |type |Default |description| | --------------------- |:---------:|:---------:|:--------- | |to |number |- |Upper limit (inclusive) |from |number |- |Lower limit (inclusive)

createStreamFromArrayRandom

Creates a stream that randomly produces a number of values from a given array in randomly delayed periods. |parameter |type |Default |description| | --------------------- |:---------:|:---------:|:--------- | |array |array |- |Array to take the values from |totalNr |number |- |Total number of values to produce |minDelay |number |500 |Minimum delay (milliseconds) |maxDelay |number |2000 |Maximum delay (milliseconds)

Example:

RxJsVisualizer.prepareCanvas(['random']);
RxJsVisualizer.startVisualize();
RxJsVisualizer.createStreamFromArrayRandom(['a', 'b', 'c'], 5)
    .subscribe(RxJsVisualizer.observerForLine(0, 'random'));
createStreamFromArraySequence

Creates a stream that produces all values in sequence from a given array in randomly delayed periods. |parameter |type |Default |description| | --------------------- |:---------:|:---------:|:--------- | |array |array |- |Array to take the values from |minDelay |number |500 |Minimum delay (milliseconds) |maxDelay |number |2000 |Maximum delay (milliseconds)

Example:

RxJsVisualizer.prepareCanvas(['seq']);
RxJsVisualizer.startVisualize();
RxJsVisualizer.createStreamFromArraySequence(['a', 'b', 'c'])
    .subscribe(RxJsVisualizer.observerForLine(0, 'seq'));
createStreamFromArrayOnClick

Creates a stream that randomly produces values from at button clicks. With additional buttons also an error and complete can be triggered. |parameter |type |Default |description| | --------------------- |:---------:|:---------:|:--------- | |array |array |- |Array to take the values from |buttonProduceId |string |- |Id of the element that triggers production of a value |buttonCompleteId |string |- |Id of the element that triggers completion of the observable |buttonErrorId |string |- |Id of the element that triggers an error for the observable

Example:

RxJsVisualizer.prepareCanvas(['click']);
RxJsVisualizer.startVisualize();
RxJsVisualizer.createStreamFromArrayOnClick(['a', 'b', 'c'], 'btnNext', 'btnComplete', 'btnError')
    .subscribe(RxJsVisualizer.observerForLine(0));
createStreamFromSubjectOnClick

Same as createStreamFromArrayOnClick, but the values are produced at the subject that is given as the first parameter. |parameter |type |Default |description| | --------------------- |:---------:|:---------:|:--------- | |array |Subject |- |Subject that will receive the produced values |buttonProduceId |string |- |Id of the element that triggers production of a value |buttonCompleteId |string |- |Id of the element that triggers completion of the observable |buttonErrorId |string |- |Id of the element that triggers an error for the observable

Example:

RxJsVisualizer.prepareCanvas(['Event']);
RxJsVisualizer.startVisualize();
const obs = new Subject();
RxJsVisualizer.createStreamFromSubjectOnClick(obs, 'btnNext', 'btnComplete', 'btnError')
    .subscribe(RxJsVisualizer.observerForLine(0));
obs.next('Started');
setInterval(() => obs.next(new Date().getSeconds()), 1000);
operators

One operator is available to draw produced items to a timeline.

draw

This pipeable operator works similar to observerForLine, but it can used inside a pipe(). |parameter |type |Default |description| | --------------------- |:---------:|:---------:|:--------- | |lineNr |number |- |Number of the timeline where this observer shall draw its values (zero-based). |header |String |'' |This header is only used for the log output to identify the source of the output. For the graphical display this value is ignored. |shouldIgnoreSymbols |boolean |false |If set to true, no symbols are used for this timeline, no matter if there is a symbol defined for the text or not. |valueMapper |function |- |If set, this function is called for each value before it is written/drawn to the timeline. Example: observerForLine(0, 'name', false, x => x.substr(0, 2))

It has to be imported from RxJsVIsualizer.opertors:

const { draw } = RxJsVisualizer.operators;

or for Angular/Ionic

import {  draw } from '@rgrueneis/rxjs-visualizer';

Example:

RxJsVisualizer.prepareCanvas(['values', 'times10']);
RxJsVisualizer.createStreamFromArraySequence([10, 11, 12, 13, 14])
    .pipe(
        draw(0, '', true),
        map(x => x * 10)
    )
    .subscribe(RxJsVisualizer.observerForLine(1, '*10:', true));
DrawingSymbol

This class represents a symbol (marble) that can be used to be drawn instead of a specific text. The constructor takes an option object with the following properties |parameter |type |Default |description| | --------------------- |:---------:|:---------:|:--------- | |text |string |- |Text to be displayed |color |string |'black' |Color used for the symbol |shape |string |'' |Shape of the symbol |imageUrl |string |'' |Path to an image file |strokeOnly |boolean |false |If the symbol is a shape, this flag specifies, if the shape is filled or only stroked.

What is actually drawn? 1. if the imageUrl is set, the image is drawn 2. if imageUrl is not set and a shape is given, the shape is drawn filled with the given color 3. if neither imageUrl nor shape is given, the text is written in the given color

Example shape:

symbols['[object MouseEvent]'] = new DrawingSymbol({ color: 'blue', shape: 'circle' });

Example image:

symbols['[object MouseEvent]'] = new DrawingSymbol({ imageUrl: 'images/flash.png' });
1.3.6

1 year ago

1.3.5

1 year ago

1.3.4

2 years ago

1.3.3

2 years ago

1.3.2

2 years ago

1.3.1

2 years ago

1.2.1

4 years ago

1.2.0

4 years ago

1.1.0

4 years ago

1.0.2

4 years ago

1.0.1

4 years ago

1.0.0

4 years ago

0.9.9

4 years ago

0.9.8

4 years ago

0.9.7

4 years ago

0.9.6

5 years ago

0.9.5

5 years ago

0.9.4

5 years ago

0.9.3

5 years ago

0.9.2

5 years ago

0.9.1

5 years ago

0.9.0

5 years ago

0.8.9

5 years ago

0.8.8

5 years ago

0.8.5

5 years ago

0.8.4

5 years ago

0.8.3

5 years ago

0.8.2

5 years ago

0.8.1

5 years ago