[!NOTE] This is one of 199 standalone projects, maintained as part of the @thi.ng/umbrella monorepo and anti-framework.
🚀 Please help me to work full-time on these projects by sponsoring me on GitHub. Thank you! ❤️
Unified mouse, mouse wheel & multi-touch event stream abstraction. This is a support package for @thi.ng/rstream.
STABLE - used in production
Search or submit any issues for this package
The gestureStream()
now supports external zoom control/resetting via providing
a subscription as zoom
option. That itself isn't a breaking change, however a
result of this is that the GestureEvent
s emitted by the stream do not always
contain the original DOM
event
anymore (i.e. not in the case when the zoom factor is being reset via attached
subscription).
Multi-touch support has been added in v2.0.0, resulting in a complete
rewrite of gestureStream()
and new event data formats.
- @thi.ng/hdom - Lightweight vanilla ES6 UI component trees with customizable branch-local behaviors
- @thi.ng/rdom - Lightweight, reactive, VDOM-less UI/DOM components with async lifecycle and @thi.ng/hiccup compatible
yarn add @thi.ng/rstream-gestures
ESM import:
import * as gest from "@thi.ng/rstream-gestures";
Browser ESM import:
<script type="module" src="https://esm.run/@thi.ng/rstream-gestures"></script>
For Node.js REPL:
const gest = await import("@thi.ng/rstream-gestures");
Package sizes (brotli'd, pre-treeshake): ESM: 1.20 KB
Note: @thi.ng/api is in most cases a type-only import (not used at runtime)
15 projects in this repo's /examples directory are using this package:
Screenshot | Description | Live demo | Source |
---|---|---|---|
Canvas based dial widget | Demo | Source | |
Interactive visualization of closest points on ellipses | Demo | Source | |
Interactive inverse FFT toy synth | Demo | Source | |
Doodle w/ K-nearest neighbor search result visualization | Demo | Source | |
K-nearest neighbor search in an hash grid | Demo | Source | |
Mouse gesture / stroke analysis, simplification, corner detection | Demo | Source | |
Interactive pattern drawing demo using transducers | Demo | Source | |
Canvas based Immediate Mode GUI components | Demo | Source | |
Minimal IMGUI usage example | Demo | Source | |
Worker based, interactive Mandelbrot visualization | Demo | Source | |
Basic rstream-gestures multi-touch demo | Demo | Source | |
Minimal rstream dataflow graph | Demo | Source | |
Minimal shader graph developed during livestream #2 | Demo | Source | |
Multi-layer vectorization & dithering of bitmap images | Demo | Source | |
rdom & WebGL-based image channel editor | Demo | Source |
All native events are abstracted into one of the following event types:
-
move
- movemove -
start
- mousedown / touchstart -
drag
- mousemove (whilst dragging) / touchmove -
end
- mouseup / touchend / touchcancel -
zoom
- wheel
The stream emits
GestureEvent
objects of:
-
type - Current translated/abstracted event type (
GestureType
) - event - Original DOM event
-
pos - Event position (transformed as per
GestureStreamOpts
) - active - Active cursors (i.e. ongoing drag / touch gestures)
-
buttons - Mouse button bitmask (same as in standard
MouseEvent
), or, ifisTouch
is true, number ofactive
touches. -
zoom - Current zoom factor (as per
GestureStreamOpts
config) -
zoomDelta - Last
WheelEvent
's transformeddeltaY
,wheelDeltaY
-
isTouch - True, if original event was a
TouchEvent
// example mouse gesture event
{
"type": "drag"
"event": MouseEvent,
"pos": [254, 169],
"active": [
{
"id": 0, // always 0 for mouse gestures
"start": [443, 37],
"pos": [254, 169],
"delta": [-189, 132]
}
],
"buttons": 2, // right button pressed
"zoom": 1,
"zoomDelta": 0,
"isTouch": false
}
See the
GestureStreamOpts
config options for further details.
import { gestureStream } from "@thi.ng/rstream-gestures";
import { trace } from "@thi.ng/rstream";
import { comp, dedupe, filter, map, pluck } from "@thi.ng/transducers";
// create event stream with custom options
const gestures = gestureStream(document.body, { smooth: 0.01 });
// subscription logging zoom value changes
gestures.subscribe(
// trace is simply logging received values to console
trace("zoom"),
// composed transducer, `dedupe` ensures only changed values are received
comp(pluck("zoom"), dedupe())
);
// another subscription computing & logging drag gesture distance(s)
gestures.subscribe(
trace("distance"),
comp(
filter((e) => e.type === "drag"),
map((e) => e.active.map((g) => Math.hypot(...g.delta)))
)
);
For some applications (e.g. graphical editors), it can be helpful to reset the zoom value. This can be done by supplying a stream/subscription as part of the config options:
import { reactive } from "@thi.ng/rstream";
import { gestureStream } from "@thi.ng/rstream-gestures";
// create stream for initial zoom value & for resetting
const zoomReset = reactive(1);
// create gesture stream w/ zoom subscription
const gestures = gestureStream(document.body, {
smooth: 0.01,
zoom: zoomReset
});
// ... then to reset the zoom at some point (e.g to zoom=2)
zoomReset.next(2);
- Karsten Schmidt (Main author)
- Arthur Carabott
- Matei Adriel
If this project contributes to an academic publication, please cite it as:
@misc{thing-rstream-gestures,
title = "@thi.ng/rstream-gestures",
author = "Karsten Schmidt and others",
note = "https://thi.ng/rstream-gestures",
year = 2018
}
© 2018 - 2024 Karsten Schmidt // Apache License 2.0