Skip to content

Commit

Permalink
[added] dragSystem
Browse files Browse the repository at this point in the history
Summary: Closes #65

Reviewers: O2 Material Motion, O3 Material JavaScript platform reviewers, #material_motion, featherless

Reviewed By: O2 Material Motion, #material_motion, featherless

Subscribers: featherless

Tags: #material_motion

Differential Revision: http://codereview.cc/D3085
  • Loading branch information
appsforartists committed Apr 24, 2017
1 parent 410af06 commit e9dcb39
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 161 deletions.
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export * from './typeGuards';
export * from './properties';
export * from './observables';
export * from './interactions';
export * from './systems';

export * from './MotionRuntime';
export { default as MotionRuntime } from './MotionRuntime';
Expand Down
30 changes: 21 additions & 9 deletions packages/core/src/interactions/Draggable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,44 @@
import createProperty from '../properties/createProperty';

import {
Observable,
MotionObservable,
} from '../observables/MotionObservable';

import {
dragSystem,
} from '../systems/dragSystem';

import {
DragSystem,
PartialPointerEvent,
Point2D,
PropertyObservable,
} from '../types';

import {
GestureRecognitionState,
} from '../GestureRecognitionState';

export type PointerEventStreams = {
down$: Observable<PartialPointerEvent>;
move$: Observable<PartialPointerEvent>;
up$: Observable<PartialPointerEvent>;
export type DraggableArgs = {
down$: MotionObservable<PartialPointerEvent>,
move$: MotionObservable<PartialPointerEvent>,
up$: MotionObservable<PartialPointerEvent>,
system: DragSystem,
};

export class Draggable {
state: PropertyObservable<GestureRecognitionState> = createProperty<GestureRecognitionState>({ initialValue: GestureRecognitionState.POSSIBLE });
recognitionThreshold: PropertyObservable<number> = createProperty<number>({ initialValue: 16 });
down$: Observable<PartialPointerEvent>;
move$: Observable<PartialPointerEvent>;
up$: Observable<PartialPointerEvent>;
down$: MotionObservable<PartialPointerEvent>;
move$: MotionObservable<PartialPointerEvent>;
up$: MotionObservable<PartialPointerEvent>;
system: DragSystem;

constructor({ down$, move$, up$ }: PointerEventStreams) {
constructor({ down$, move$, up$, system = dragSystem }: DraggableArgs) {
this.down$ = down$;
this.move$ = move$;
this.up$ = up$;
this.system = system;
}
}
export default Draggable;
122 changes: 122 additions & 0 deletions packages/core/src/systems/dragSystem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/** @license
* Copyright 2016 - present The Material Motion Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/

import {
Draggable,
} from '../interactions/Draggable';

import {
MotionObservable,
} from '../observables/MotionObservable';

import {
GestureRecognitionState,
} from '../GestureRecognitionState';

import {
Observable,
Observer,
PartialPointerEvent,
Point2D,
Subscription,
} from '../types';

import {
isPointerEvent,
} from '../typeGuards';

export function dragSystem({
down$,
move$,
up$,
state,
recognitionThreshold,
}: Draggable): MotionObservable<Point2D> {
return new MotionObservable<Point2D>(
(observer: Observer<Point2D>) => {
let moveSubscription: Subscription;
const downSubscription: Subscription = down$.subscribe(
(downEvent: PointerEvent) => {
if (isPointerEvent(downEvent)) {
// The `as Element` is a workaround for
// https://github.com/Microsoft/TypeScript/issues/299
(downEvent.target as Element).setPointerCapture(downEvent.pointerId);
}

moveSubscription = move$.merge(up$)._filter(
(nextEvent: PartialPointerEvent) => nextEvent.pointerId === downEvent.pointerId
).subscribe(
(nextEvent: PartialPointerEvent) => {
const atRest = nextEvent.type.includes('up');

const translation = {
x: nextEvent.pageX - downEvent.pageX,
y: nextEvent.pageY - downEvent.pageY,
};

switch (state.read()) {
case GestureRecognitionState.POSSIBLE:
if (Math.sqrt(translation.x ** 2 + translation.y ** 2) > recognitionThreshold.read()) {
state.write(GestureRecognitionState.BEGAN);
}
break;

case GestureRecognitionState.BEGAN:
state.write(GestureRecognitionState.CHANGED);
break;

case GestureRecognitionState.CHANGED:
if (!atRest) {
state.write(GestureRecognitionState.CHANGED);
}
break;

default:break;
}

if (atRest) {
// This would be a takeWhile if we were using an Observable
// implementation that supported completion.
moveSubscription.unsubscribe();

if (state.read() === GestureRecognitionState.POSSIBLE) {
state.write(GestureRecognitionState.FAILED);
} else {
state.write(GestureRecognitionState.ENDED);
}
}

observer.next(translation);

if (atRest) {
state.write(GestureRecognitionState.POSSIBLE);
}
}
);
}
);

return () => {
downSubscription.unsubscribe();

if (moveSubscription) {
moveSubscription.unsubscribe();
}
};
}
);
}
export default dragSystem;
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* under the License.
*/

export * from './createDragStream';
export { default as createDragStream } from './createDragStream';
export * from './dragSystem';
export { default as dragSystem } from './dragSystem';

export default undefined;
28 changes: 14 additions & 14 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ export {
ObservableWithMotionOperators,
} from './operators'

import {
Draggable,
} from './interactions/Draggable';

import {
SpringT,
} from './interactions/Spring';

import {
MotionObservable,
} from './observables/MotionObservable';
Expand Down Expand Up @@ -100,9 +108,9 @@ export type Point2D = {

/**
* There are 2 competing input events on the Web: `PointerEvent`s and
* `TouchEvent`s. Our gesture system only needs 3 properties: x, y, and and ID.
* In both models, `pageX` and `pageY` are provided. `TouchEvent` calls its ID
* `identifier`; whereas, `PointerEvent` uses `pointerId`.
* `TouchEvent`s. Our gesture system only needs 4 properties: x, y, type and an
* ID. In both models, `pageX` and `pageY` are provided. `TouchEvent` calls its
* ID `identifier`; whereas, `PointerEvent` uses `pointerId`.
*
* `PartialPointerEvent` is the subset we care about. `PointerEvent` already
* has this shape. `TouchEvent` can be trivially converted by extracting the
Expand All @@ -112,6 +120,7 @@ export type PartialPointerEvent = {
pageX: number;
pageY: number;
pointerId: number;
type: 'pointerdown' | 'pointermove' | 'pointerup';
};

export type Read<T> = () => T;
Expand All @@ -133,17 +142,8 @@ export interface MotionElement {

export type EqualityCheck = (a: any, b: any) => boolean;

export type SpringProperties<T> = {
state: PropertyObservable<State>,
enabled: PropertyObservable<boolean>,
destination: PropertyObservable<T>,
initialValue: PropertyObservable<T>,
initialVelocity: PropertyObservable<T>,
friction: PropertyObservable<number>,
tension: PropertyObservable<number>,
threshold: PropertyObservable<number>,
};
export type SpringSystem<T extends number | Point2D> = (spring: SpringProperties<T>) => MotionObservable<T>;
export type DragSystem = (interaction: Draggable) => MotionObservable<Point2D>;
export type SpringSystem<T extends number | Point2D> = (interaction: SpringT<T>) => MotionObservable<T>;

export type Dict<T> = {
[index: string]: T,
Expand Down
134 changes: 0 additions & 134 deletions packages/experimental-addons/src/gestures/createDragStream.ts

This file was deleted.

2 changes: 0 additions & 2 deletions packages/experimental-addons/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,4 @@ export { default as PropertyKind } from './PropertyKind';
export * from './InputKind';
export { default as InputKind } from './InputKind';

export * from './gestures';

export default undefined;

0 comments on commit e9dcb39

Please sign in to comment.