Skip to content

Commit

Permalink
refactor(gestures): no longer use hammer for drag gestures
Browse files Browse the repository at this point in the history
  • Loading branch information
manucorporat authored and adamdbradley committed Jul 15, 2016
1 parent 11a24b9 commit 5909fa4
Show file tree
Hide file tree
Showing 12 changed files with 292 additions and 309 deletions.
16 changes: 16 additions & 0 deletions src/components/app/test/gesture-collision/page1.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,22 @@ <h3>Page 1</h3>
</ion-item-options>
</ion-item-sliding>

<ion-item-sliding>
<ion-item>LEFT button</ion-item>

<ion-item-options side="left">
<button>Test</button>
</ion-item-options>
</ion-item-sliding>

<ion-item-sliding>
<ion-item>RIGHT button</ion-item>

<ion-item-options>
<button>Test</button>
</ion-item-options>
</ion-item-sliding>

<button ion-item (click)="goToPage1()">Push same page</button>

<ion-item>
Expand Down
154 changes: 23 additions & 131 deletions src/components/item/item-sliding-gesture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,29 @@ import { List } from '../list/list';
import { closest, Coordinates, pointerCoord } from '../../util/dom';
import { PointerEvents, UIEventManager } from '../../util/ui-event-manager';
import { GestureDelegate, GestureOptions, GesturePriority } from '../../gestures/gesture-controller';
import { PanGesture } from '../../gestures/drag-gesture';

const DRAG_THRESHOLD = 10;
const MAX_ATTACK_ANGLE = 20;

export class ItemSlidingGesture {
export class ItemSlidingGesture extends PanGesture {
private preSelectedContainer: ItemSliding = null;
private selectedContainer: ItemSliding = null;
private openContainer: ItemSliding = null;
private events: UIEventManager = new UIEventManager(false);
private panDetector: PanXRecognizer = new PanXRecognizer(DRAG_THRESHOLD, MAX_ATTACK_ANGLE);
private pointerEvents: PointerEvents;
private firstCoordX: number;
private firstTimestamp: number;
private gesture: GestureDelegate;

constructor(public list: List) {
this.gesture = list.gestureCtrl.create('item-sliding', {
priority: GesturePriority.Interactive,
});

this.pointerEvents = this.events.pointerEvents({
element: list.getNativeElement(),
pointerDown: this.pointerStart.bind(this),
pointerMove: this.pointerMove.bind(this),
pointerUp: this.pointerEnd.bind(this),
super(list.getNativeElement(), {
maxAngle: MAX_ATTACK_ANGLE,
threshold: DRAG_THRESHOLD,
gesture: list.gestureCtrl.create('item-sliding', {
priority: GesturePriority.SlidingItem,
})
});
}

private pointerStart(ev: any): boolean {
canStart(ev: any): boolean {
if (this.selectedContainer) {
return false;
}
Expand All @@ -42,85 +36,50 @@ export class ItemSlidingGesture {
this.closeOpened();
return false;
}

// Close open container if it is not the selected one.
if (container !== this.openContainer) {
this.closeOpened();
}

// Try to start gesture
if (!this.gesture.start()) {
this.gesture.release();
return false;
}

let coord = pointerCoord(ev);
this.preSelectedContainer = container;
this.panDetector.start(coord);
this.firstCoordX = coord.x;
this.firstTimestamp = Date.now();
return true;
}

private pointerMove(ev: any) {
if (this.selectedContainer) {
this.onDragMove(ev);
return;
}
let coord = pointerCoord(ev);
if (this.panDetector.detect(coord)) {
if (this.panDetector.isPanX() && this.gesture.capture()) {
this.onDragStart(ev, coord);
return;
}

// Detection/capturing was not successful, aborting!
this.closeOpened();
this.pointerEvents.stop();
}
}

private pointerEnd(ev: any) {
this.gesture.release();
if (this.selectedContainer) {
this.onDragEnd(ev);
} else {
this.closeOpened();
}
}

private onDragStart(ev: any, coord: Coordinates): boolean {
let container = getContainer(ev);
if (!container) {
console.debug('onDragStart, no itemContainerEle');
return false;
}
onDragStart(ev: any) {
ev.preventDefault();

let coord = pointerCoord(ev);
this.selectedContainer = this.openContainer = this.preSelectedContainer;
container.startSliding(coord.x);
this.selectedContainer.startSliding(coord.x);
}

private onDragMove(ev: any) {
let coordX = pointerCoord(ev).x;
onDragMove(ev: any) {
ev.preventDefault();

let coordX = pointerCoord(ev).x;
this.selectedContainer.moveSliding(coordX);
}

private onDragEnd(ev: any) {
onDragEnd(ev: any) {
ev.preventDefault();

let coordX = pointerCoord(ev).x;
let deltaX = (coordX - this.firstCoordX);
let deltaT = (Date.now() - this.firstTimestamp);

let openAmount = this.selectedContainer.endSliding(deltaX / deltaT);
this.selectedContainer = null;
this.preSelectedContainer = null;
}

notCaptured(ev: any) {
this.closeOpened();
}

closeOpened(): boolean {
this.selectedContainer = null;
this.gesture.release();

if (this.openContainer) {
this.openContainer.close();
Expand All @@ -131,8 +90,7 @@ export class ItemSlidingGesture {
}

destroy() {
this.gesture.destroy();
this.events.unlistenAll();
super.destroy();
this.closeOpened();

this.list = null;
Expand All @@ -148,70 +106,4 @@ function getContainer(ev: any): ItemSliding {
return (<any>ele)['$ionComponent'];
}
return null;
}

class AngleRecognizer {
private startCoord: Coordinates;
private sumCoord: Coordinates;
private dirty: boolean;
private _angle: any = null;
private threshold: number;

constructor(threshold: number) {
this.threshold = threshold ** 2;
}

start(coord: Coordinates) {
this.startCoord = coord;
this._angle = 0;
this.dirty = true;
}

angle(): any {
return this._angle;
}

detect(coord: Coordinates): boolean {
if (!this.dirty) {
return false;
}
let deltaX = (coord.x - this.startCoord.x);
let deltaY = (coord.y - this.startCoord.y);
let distance = deltaX * deltaX + deltaY * deltaY;
if (distance >= this.threshold) {
this._angle = Math.atan2(deltaY, deltaX);
this.dirty = false;
return true;
}
return false;
}
}


class PanXRecognizer extends AngleRecognizer {
private _isPanX: boolean;
private maxAngle: number;

constructor(threshold: number, maxAngle: number) {
super(threshold);
this.maxAngle = maxAngle * (Math.PI / 180);
}

start(coord: Coordinates) {
super.start(coord);
this._isPanX = false;
}

isPanX(): boolean {
return this._isPanX;
}

detect(coord: Coordinates): boolean {
if (super.detect(coord)) {
let angle = Math.abs(this.angle());
this._isPanX = (angle < this.maxAngle || Math.abs(angle - Math.PI) < this.maxAngle);
return true;
}
return false;
}
}
}
1 change: 1 addition & 0 deletions src/components/list/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export class List extends Ion {
} else if (!this._slidingGesture) {
console.debug('enableSlidingItems');
this._slidingGesture = new ItemSlidingGesture(this);
this._slidingGesture.listen();
}
}

Expand Down

0 comments on commit 5909fa4

Please sign in to comment.