Samsara interprets continuous user input as a stream. Lest we forget, user input has always been a stream. When we write,

window.addEventListener('mousemove', function(event){
    console.log(event.offsetX);
});

we are subscribing to a stream of data emitted from the DOM. But the DOM only starts us off: it gives us a spout to listen to. The power of streams comes from their ability to transform and stitch together to build pipelines. As it stands with the DOM, the only way to process its streaming input data is to put all your business logic into the listener itself, which is a boon to modularity and flexibility.

Input Streams

Samsara gets around these problems by converting these DOM events into its own streams. Just like a Transitionable, values from user input can be subscribed from and mapped directly to nodes to affect layout. Samsara comes with the following input streams:

Input Description Data
MouseInput Captures mouse drag events delta, value, cumulate, velocity, clientX, clientY, offsetX, offsetY
TouchInput Captures touch events delta, value, cumulate, velocity, clientX, clientY, count, touchId
ScrollInput Captures mouse wheel and trackpad events delta, value, cumulate, velocity, clientX, clientY, offsetX, offsetY
PinchInput Captures the distance between two finger events delta, value, velocity, center, touchIds
RotateInput Captures the rotation between two finger events delta, value, velocity, center, touchIds
ScaleInput Captures the relative stretching between two finger events delta, scale, distance, center, touchIds

All Samsara streams emit start, update and end events. For input events, these are derived from the native DOM events. For instance, MouseInput listens to mouse drag events, and will internally convert mousedown, mousemove and mouseup into start, update and end respectively. Similarly, TouchInput will convert touchstart, touchmove and touchend into start, update and end. Scrollinput will define an end event by debouncing DOM wheel events (since there is no DOM wheelend event).

Samsara inputs do more than just unify events into a common syntax. They also provide derived data like deltas, velocities, and other quantities that it computes internally from the raw DOM event information. This makes it easy to recognize gestures, apply effects like carrying the velocity of a drag into another transition, and combine various sources of user input together. Here's an example of some of the data provided by MouseInput:

See the Pen input-data by SamsaraJS (@samsaraJS) on CodePen.


Inputs need to subscribe to a source of DOM event data, such as a Context or Surface. They will then be listening to DOM events originating from the source. The following code indicates how to have a Surface follow a mouse's position.

var mouse = new MouseInput();

// The mouse now listens to the DOM events originating from the surface
mouse.subscribe(surface);

// Map the mouse date to a translation
var transform = mouse.map(function(data){
    return Transform.translate(data.cumulate);
});

See the Pen mouse-drag by SamsaraJS (@samsaraJS) on CodePen.

Unifying Inputs with GenericInput

Samsara comes with one other input, called GenericInput, which acts to unify several inputs together. This is useful for unifying desktop and mobile experiences. For instance, you can unify touch and mouse events into one input, and this will behave appropriately on desktop environments and touch screens. Another example is unifying scroll and touch events, to get consistent behavior between a mouse/trackpad and a touch interface.

You can register various Samsara inputs (similar to registering custom easing curves in a Transitionable) for GenericSync globally, and then later instantiate specific subsets of them where you need. Here's an example of how to use GenericInput.

var MouseInput = require('samsara/inputs/MouseInput');
var TouchInput = require('samsara/inputs/TouchInput');
var ScrollInput = require('samsara/inputs/ScrollInput');
var GenericInput = require('samsara/inputs/GenericInput');

// in main.js
// register all the inputs you need in {id : constructor} pairs
// the Ids registered can be used globally in the application
GenericInput.register({
   mouse : MouseInput,
   touch : TouchInput,
   scroll : ScrollInput
});

// in myFile.js
// create an instance of an input that unifies some subset of the registered input Ids
var mouseTouchInput = new GenericInput(['mouse', 'touch']);
var scrollInput = new GenericInput(['scroll', 'touch']);