Drag

A drag's samples and what shapes them: Sample, what DragRecognizer's drags give at each step; Axis, the axes one moves on; and the constraints a binding applies to a sample's offset, with a rubber band past them (constrain, within, withinBounds), or to keep an element inside a container (boundsWithin, keepPlace after a resize). A binding moves the element from the shaped samples, and flings it at the end.

import * as Drag from "@wardic/core/Drag"

const samples = DragRecognizer.drag(card, { axis: "x" }).pipe(
  Drag.withinBounds({ x: { min: 0, max: 200 } }, { elastic: 0.35 }),
)

Interfaces

AxisRange

A range on one axis. Either end can be left out: { min: 0 } holds it above 0, and lets it go as far as it likes the other way.

Properties

max?
readonly max?: number;

The most it goes to.

min?
readonly min?: number;

The least it goes to.


Bounds

A range on each axis. An axis left out is free.

Properties

x?
readonly x?: AxisRange;

The range across.

y?
readonly y?: AxisRange;

The range down.


Edges

A box's edges, in its Environment's coordinates: a Probe.Bounds is one.

Properties

bottom
readonly bottom: number;

Its bottom edge.

left
readonly left: number;

Its left edge.

readonly right: number;

Its right edge.

top
readonly top: number;

Its top edge.


Sample

One step of a drag, as DragRecognizer's drags give it: where the pointer is, how far and how fast it's moved.

Properties

axis
readonly axis: Axis;

The axes it moves on, read at its start: its drag's axis, or a direction-locked drag's lock. A pan's are both.

cancelled?
readonly cancelled?: boolean;

true on an "end" its watch's cancel gave: the drag ended where it is, which a binding releases with no fling and tells no app. Absent on every other sample.

delta
readonly delta: Point;

How far it's moved since the sample before.

offset
readonly offset: Point;

How far it's moved since the down that started the drag: point less the down's.

phase
readonly phase: "start" | "end" | "move";

"start" once it's past its threshold, "move" as it moves, "end" at its release or a cancel. A cancel ends at the last move's point, with the moves' velocity. A drag whose release was lost ends at the pointer's first move with no button pressed, or at its next down: an "end" at the last pressed point, with no delta and no velocity.

point
readonly point: Point;

Where the pointer is, in the Environment's coordinates.

raw?
readonly raw?: unknown;

The platform's own event behind it, which core never reads: a binding hands it to an app's callback.

scroll
readonly scroll: Point;

The scroll counted into point since the down: point less scroll is where the pointer is on the screen.

timeStamp
readonly timeStamp: number;

The time, in ms, of the event behind it: for a move a scroll made, the scroll's.

velocity
readonly velocity: Point;

The pointer's velocity on each axis, in units a second, over the drag's last 100 ms, as Motion's. The "end" sample counts the release point, so a pause before letting go slows it, down to none.

Type Aliases

Axis

type Axis = "x" | "y" | "xy";

The axes a drag moves on: "x" or "y" alone, or "xy" for a free drag. A one-axis drag claims only its axis, so a drag inside that moves on the other one keeps its own gesture.

Variables

within

const within: {
  (bounds, options?): (sample) => Sample;
  (sample, bounds, options?): Sample;
};

sample with its offset kept within bounds, as constrain keeps a number: elastic 0, a hard stop, unless it's given. An axis left out is free; delta and velocity stay the pointer's. For samples one at a time, as a watch's handler has them; withinBounds shapes a Stream's.

Call Signature

(bounds, options?): (sample) => Sample;
Parameters
bounds

Bounds

options?
elastic?

number

Returns

(sample) => Sample

Call Signature

(
   sample, 
   bounds, 
   options?
): Sample;
Parameters
sample

Sample

bounds

Bounds

options?
elastic?

number

Returns

Sample

Example

const shaped = Drag.within(sample, { x: { min: 0, max: 200 } }, { elastic: 0.35 })

withinBounds

const withinBounds: {
  (bounds, options?): <E, R>(stream) => Stream<Sample, E, R>;
  <E, R>(stream, bounds, options?): Stream<Sample, E, R>;
};

A drag's samples with each one's offset kept within bounds, as within keeps one: for a Stream of them. delta and velocity stay the pointer's: a binding places the element from offset, and the others stay a true record of how the pointer moved.

Call Signature

(bounds, options?): <E, R>(stream) => Stream<Sample, E, R>;
Parameters
bounds

Bounds

options?
elastic?

number

Returns

<E, R>(stream) => Stream<Sample, E, R>

Call Signature

<E, R>(
   stream, 
   bounds, 
   options?
): Stream<Sample, E, R>;
Type Parameters
E

E

R

R

Parameters
stream

Stream<Sample, E, R>

bounds

Bounds

options?
elastic?

number

Returns

Stream<Sample, E, R>

Example

DragRecognizer.drag(card).pipe(Drag.withinBounds({ x: { min: 0, max: 200 } }, { elastic: 0.5 }))

Functions

boundsWithin()

function boundsWithin(own, container): Bounds;

The bounds on an element's x and y that keep its box inside container, as Motion's drag constraints given an element. On an axis where the box is the bigger they turn around, so it can be dragged to show what overflows and no further. own is the element's box with no x or y of its own: its layout box.

Parameters

own

Edges

container

Edges

Returns

Bounds

Example

const bounds = Drag.boundsWithin(cardBox, frameBox)

constrain()

function constrain(
   v, 
   range, 
   elastic
): number;

v kept within range, with elastic resistance past it, as Motion's applyConstraints: past an end, only elastic of the overshoot is kept. So elastic 0 holds it at the end, 1 lets it go freely, and between them it stretches like a rubber band. Within the range, or with no range, it's v.

Parameters

v

number

range

AxisRange | undefined

elastic

number

Returns

number

Example

Drag.constrain(130, { min: 0, max: 100 }, 0.35) // 110.5

keepPlace()

function keepPlace(
   position, 
   axis, 
   from, 
   to
): Point;

position moved to keep its place, from from within to: an element's x and y after a resize changes the bounds that keep it inside its container, as Motion's. Only on the axes axis moves, and where both bounds have both ends; elsewhere it stays.

Parameters

position

Point

axis

Axis

from

Bounds

to

Bounds

Returns

Point


progressWithin()

function progressWithin(
   value, 
   min, 
   max
): number;

Where value sits between min and max: 0 at min, 1 at max, held between; ½ for a range of no length.

Parameters

value

number

min

number

max

number

Returns

number


sameBounds()

function sameBounds(a, b): boolean;

Whether two bounds are the same on both axes: a resize that changed neither leaves an element where it is.

Parameters

a

Bounds

b

Bounds

Returns

boolean