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.
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.
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']);