mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-22 21:48:42 +08:00

committed by
Adam Bradley

parent
6506cd5982
commit
8585427fb4
@ -24,7 +24,7 @@ export class MenuContentGesture extends SlideEdgeGesture {
|
|||||||
|
|
||||||
canStart(ev: any): boolean {
|
canStart(ev: any): boolean {
|
||||||
let menu = this.menu;
|
let menu = this.menu;
|
||||||
if (!menu.enabled || !menu.swipeEnabled) {
|
if (!menu.canSwipe()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (menu.isOpen) {
|
if (menu.isOpen) {
|
||||||
@ -36,7 +36,7 @@ export class MenuContentGesture extends SlideEdgeGesture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set CSS, then wait one frame for it to apply before sliding starts
|
// Set CSS, then wait one frame for it to apply before sliding starts
|
||||||
onSlideBeforeStart(slide: SlideData, ev: any) {
|
onSlideBeforeStart(ev: any) {
|
||||||
console.debug('menu gesture, onSlideBeforeStart', this.menu.side);
|
console.debug('menu gesture, onSlideBeforeStart', this.menu.side);
|
||||||
this.menu.swipeStart();
|
this.menu.swipeStart();
|
||||||
}
|
}
|
||||||
@ -44,7 +44,15 @@ export class MenuContentGesture extends SlideEdgeGesture {
|
|||||||
onSlide(slide: SlideData, ev: any) {
|
onSlide(slide: SlideData, ev: any) {
|
||||||
let z = (this.menu.side === 'right' ? slide.min : slide.max);
|
let z = (this.menu.side === 'right' ? slide.min : slide.max);
|
||||||
let stepValue = (slide.distance / z);
|
let stepValue = (slide.distance / z);
|
||||||
console.debug('menu gesture, onSlide', this.menu.side, 'distance', slide.distance, 'min', slide.min, 'max', slide.max, 'z', z, 'stepValue', stepValue);
|
|
||||||
|
console.debug(
|
||||||
|
'menu gesture, onSlide', this.menu.side,
|
||||||
|
'distance', slide.distance,
|
||||||
|
'min', slide.min,
|
||||||
|
'max', slide.max,
|
||||||
|
'z', z,
|
||||||
|
'stepValue', stepValue);
|
||||||
|
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
this.menu.swipeProgress(stepValue);
|
this.menu.swipeProgress(stepValue);
|
||||||
}
|
}
|
||||||
@ -70,28 +78,25 @@ export class MenuContentGesture extends SlideEdgeGesture {
|
|||||||
'shouldCompleteLeft', shouldCompleteLeft,
|
'shouldCompleteLeft', shouldCompleteLeft,
|
||||||
'shouldCompleteRight', shouldCompleteRight,
|
'shouldCompleteRight', shouldCompleteRight,
|
||||||
'currentStepValue', currentStepValue);
|
'currentStepValue', currentStepValue);
|
||||||
|
|
||||||
this.menu.swipeEnd(shouldCompleteLeft, shouldCompleteRight, currentStepValue);
|
this.menu.swipeEnd(shouldCompleteLeft, shouldCompleteRight, currentStepValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
getElementStartPos(slide: SlideData, ev: any) {
|
getElementStartPos(slide: SlideData, ev: any) {
|
||||||
if (this.menu.side === 'right') {
|
if (this.menu.side === 'right') {
|
||||||
// right menu
|
|
||||||
return this.menu.isOpen ? slide.min : slide.max;
|
return this.menu.isOpen ? slide.min : slide.max;
|
||||||
}
|
}
|
||||||
|
|
||||||
// left menu
|
// left menu
|
||||||
return this.menu.isOpen ? slide.max : slide.min;
|
return this.menu.isOpen ? slide.max : slide.min;
|
||||||
}
|
}
|
||||||
|
|
||||||
getSlideBoundaries(): {min: number, max: number} {
|
getSlideBoundaries(): {min: number, max: number} {
|
||||||
if (this.menu.side === 'right') {
|
if (this.menu.side === 'right') {
|
||||||
// right menu
|
|
||||||
return {
|
return {
|
||||||
min: -this.menu.width(),
|
min: -this.menu.width(),
|
||||||
max: 0
|
max: 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// left menu
|
// left menu
|
||||||
return {
|
return {
|
||||||
min: 0,
|
min: 0,
|
||||||
|
@ -186,16 +186,17 @@ import { GestureController } from '../../gestures/gesture-controller';
|
|||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
})
|
})
|
||||||
export class Menu {
|
export class Menu {
|
||||||
private _preventTime: number = 0;
|
|
||||||
private _cntEle: HTMLElement;
|
private _cntEle: HTMLElement;
|
||||||
private _cntGesture: MenuContentGesture;
|
private _cntGesture: MenuContentGesture;
|
||||||
private _type: MenuType;
|
private _type: MenuType;
|
||||||
private _resizeUnreg: Function;
|
private _resizeUnreg: Function;
|
||||||
private _isEnabled: boolean = true;
|
private _isEnabled: boolean = true;
|
||||||
private _isSwipeEnabled: boolean = true;
|
private _isSwipeEnabled: boolean = true;
|
||||||
|
private _isAnimating: boolean = false;
|
||||||
private _isPers: boolean = false;
|
private _isPers: boolean = false;
|
||||||
private _init: boolean = false;
|
private _init: boolean = false;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
@ -378,21 +379,20 @@ export class Menu {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private _setListeners() {
|
private _setListeners() {
|
||||||
let self = this;
|
if (!this._init) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (self._init) {
|
// only listen/unlisten if the menu has initialized
|
||||||
// only listen/unlisten if the menu has initialized
|
if (this._isEnabled && this._isSwipeEnabled && !this._cntGesture.isListening) {
|
||||||
|
// should listen, but is not currently listening
|
||||||
|
console.debug('menu, gesture listen', this.side);
|
||||||
|
this._cntGesture.listen();
|
||||||
|
|
||||||
if (self._isEnabled && self._isSwipeEnabled && !self._cntGesture.isListening) {
|
} else if (this._cntGesture.isListening && (!this._isEnabled || !this._isSwipeEnabled)) {
|
||||||
// should listen, but is not currently listening
|
// should not listen, but is currently listening
|
||||||
console.debug('menu, gesture listen', self.side);
|
console.debug('menu, gesture unlisten', this.side);
|
||||||
self._cntGesture.listen();
|
this._cntGesture.unlisten();
|
||||||
|
|
||||||
} else if (self._cntGesture.isListening && (!self._isEnabled || !self._isSwipeEnabled)) {
|
|
||||||
// should not listen, but is currently listening
|
|
||||||
console.debug('menu, gesture unlisten', self.side);
|
|
||||||
self._cntGesture.unlisten();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,7 +416,7 @@ export class Menu {
|
|||||||
setOpen(shouldOpen: boolean, animated: boolean = true): Promise<boolean> {
|
setOpen(shouldOpen: boolean, animated: boolean = true): Promise<boolean> {
|
||||||
// _isPrevented is used to prevent unwanted opening/closing after swiping open/close
|
// _isPrevented is used to prevent unwanted opening/closing after swiping open/close
|
||||||
// or swiping open the menu while pressing down on the MenuToggle button
|
// or swiping open the menu while pressing down on the MenuToggle button
|
||||||
if ((shouldOpen && this.isOpen) || this._isPrevented()) {
|
if ((shouldOpen && this.isOpen) || !this._isEnabled || this._isAnimating) {
|
||||||
return Promise.resolve(this.isOpen);
|
return Promise.resolve(this.isOpen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,12 +430,20 @@ export class Menu {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
canSwipe(): boolean {
|
||||||
|
return this._isEnabled && this._isSwipeEnabled && !this._isAnimating;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
swipeStart() {
|
swipeStart() {
|
||||||
// user started swiping the menu open/close
|
// user started swiping the menu open/close
|
||||||
if (this._isEnabled && this._isSwipeEnabled && !this._isPrevented()) {
|
if (this.canSwipe()) {
|
||||||
this._before();
|
this._before();
|
||||||
this._getType().setProgressStart(this.isOpen);
|
this._getType().setProgressStart(this.isOpen);
|
||||||
}
|
}
|
||||||
@ -446,46 +454,42 @@ export class Menu {
|
|||||||
*/
|
*/
|
||||||
swipeProgress(stepValue: number) {
|
swipeProgress(stepValue: number) {
|
||||||
// user actively dragging the menu
|
// user actively dragging the menu
|
||||||
if (this._isEnabled && this._isSwipeEnabled) {
|
if (!this._isAnimating) {
|
||||||
this._prevent();
|
return;
|
||||||
this._getType().setProgessStep(stepValue);
|
|
||||||
this.ionDrag.emit(stepValue);
|
|
||||||
}
|
}
|
||||||
|
this._getType().setProgessStep(stepValue);
|
||||||
|
this.ionDrag.emit(stepValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
swipeEnd(shouldCompleteLeft: boolean, shouldCompleteRight: boolean, stepValue: number) {
|
swipeEnd(shouldCompleteLeft: boolean, shouldCompleteRight: boolean, stepValue: number) {
|
||||||
// user has finished dragging the menu
|
if (!this._isAnimating) {
|
||||||
if (this._isEnabled && this._isSwipeEnabled) {
|
return;
|
||||||
this._prevent();
|
|
||||||
|
|
||||||
let opening = !this.isOpen;
|
|
||||||
let shouldComplete = false;
|
|
||||||
if (opening) {
|
|
||||||
shouldComplete = (this.side === 'right') ? shouldCompleteLeft : shouldCompleteRight;
|
|
||||||
} else {
|
|
||||||
shouldComplete = (this.side === 'right') ? shouldCompleteRight : shouldCompleteLeft;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._getType().setProgressEnd(shouldComplete, stepValue, (isOpen: boolean) => {
|
|
||||||
console.debug('menu, swipeEnd', this.side);
|
|
||||||
this._after(isOpen);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
// user has finished dragging the menu
|
||||||
|
let opening = !this.isOpen;
|
||||||
|
let shouldComplete = false;
|
||||||
|
if (opening) {
|
||||||
|
shouldComplete = (this.side === 'right') ? shouldCompleteLeft : shouldCompleteRight;
|
||||||
|
} else {
|
||||||
|
shouldComplete = (this.side === 'right') ? shouldCompleteRight : shouldCompleteLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._getType().setProgressEnd(shouldComplete, stepValue, (isOpen: boolean) => {
|
||||||
|
console.debug('menu, swipeEnd', this.side);
|
||||||
|
this._after(isOpen);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _before() {
|
private _before() {
|
||||||
// this places the menu into the correct location before it animates in
|
// this places the menu into the correct location before it animates in
|
||||||
// this css class doesn't actually kick off any animations
|
// this css class doesn't actually kick off any animations
|
||||||
if (this._isEnabled) {
|
this.getNativeElement().classList.add('show-menu');
|
||||||
this.getNativeElement().classList.add('show-menu');
|
this.getBackdropElement().classList.add('show-backdrop');
|
||||||
this.getBackdropElement().classList.add('show-backdrop');
|
this._keyboard.close();
|
||||||
|
this._isAnimating = true;
|
||||||
this._prevent();
|
|
||||||
this._keyboard.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _after(isOpen: boolean) {
|
private _after(isOpen: boolean) {
|
||||||
@ -493,37 +497,24 @@ export class Menu {
|
|||||||
// only add listeners/css if it's enabled and isOpen
|
// only add listeners/css if it's enabled and isOpen
|
||||||
// and only remove listeners/css if it's not open
|
// and only remove listeners/css if it's not open
|
||||||
// emit opened/closed events
|
// emit opened/closed events
|
||||||
if ((this._isEnabled && isOpen) || !isOpen) {
|
this.isOpen = isOpen;
|
||||||
this._prevent();
|
this._isAnimating = false;
|
||||||
|
|
||||||
this.isOpen = isOpen;
|
(<any>this._cntEle.classList)[isOpen ? 'add' : 'remove']('menu-content-open');
|
||||||
|
|
||||||
(<any>this._cntEle.classList)[isOpen ? 'add' : 'remove']('menu-content-open');
|
this._cntEle.removeEventListener('click', this.onContentClick);
|
||||||
|
|
||||||
this._cntEle.removeEventListener('click', this.onContentClick);
|
if (isOpen) {
|
||||||
|
this._cntEle.addEventListener('click', this.onContentClick);
|
||||||
|
this.ionOpen.emit(true);
|
||||||
|
|
||||||
if (isOpen) {
|
} else {
|
||||||
this._cntEle.addEventListener('click', this.onContentClick);
|
this.getNativeElement().classList.remove('show-menu');
|
||||||
this.ionOpen.emit(true);
|
this.getBackdropElement().classList.remove('show-backdrop');
|
||||||
|
this.ionClose.emit(true);
|
||||||
} else {
|
|
||||||
this.getNativeElement().classList.remove('show-menu');
|
|
||||||
this.getBackdropElement().classList.remove('show-backdrop');
|
|
||||||
this.ionClose.emit(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _prevent() {
|
|
||||||
// used to prevent unwanted opening/closing after swiping open/close
|
|
||||||
// or swiping open the menu while pressing down on the MenuToggle
|
|
||||||
this._preventTime = Date.now() + 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _isPrevented() {
|
|
||||||
return this._preventTime > Date.now();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
@ -564,6 +555,9 @@ export class Menu {
|
|||||||
.map(m => m.enabled = false);
|
.map(m => m.enabled = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// what happens if menu is disabled while swipping?
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -572,6 +566,8 @@ export class Menu {
|
|||||||
*/
|
*/
|
||||||
swipeEnable(shouldEnable: boolean): Menu {
|
swipeEnable(shouldEnable: boolean): Menu {
|
||||||
this.swipeEnabled = shouldEnable;
|
this.swipeEnabled = shouldEnable;
|
||||||
|
// TODO
|
||||||
|
// what happens if menu swipe is disabled while swipping?
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -619,7 +615,11 @@ export class Menu {
|
|||||||
this._cntGesture && this._cntGesture.destroy();
|
this._cntGesture && this._cntGesture.destroy();
|
||||||
this._type && this._type.destroy();
|
this._type && this._type.destroy();
|
||||||
this._resizeUnreg && this._resizeUnreg();
|
this._resizeUnreg && this._resizeUnreg();
|
||||||
|
|
||||||
|
this._cntGesture = null;
|
||||||
|
this._type = null;
|
||||||
this._cntEle = null;
|
this._cntEle = null;
|
||||||
|
this._resizeUnreg = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,23 +33,32 @@ export class SlideGesture extends PanGesture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onDragStart(ev: any) {
|
onDragStart(ev: any) {
|
||||||
this.slide = {};
|
this.onSlideBeforeStart(ev);
|
||||||
this.onSlideBeforeStart(this.slide, ev);
|
|
||||||
|
|
||||||
let {min, max} = this.getSlideBoundaries(this.slide, ev);
|
|
||||||
let coord = <any>pointerCoord(ev);
|
let coord = <any>pointerCoord(ev);
|
||||||
|
let pos = coord[this.direction];
|
||||||
|
|
||||||
|
this.slide = {
|
||||||
|
min: 0,
|
||||||
|
max: 0,
|
||||||
|
pointerStartPos: pos,
|
||||||
|
pos: pos,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
elementStartPos: 0,
|
||||||
|
started: true,
|
||||||
|
delta: 0,
|
||||||
|
distance: 0,
|
||||||
|
velocity: 0,
|
||||||
|
};
|
||||||
|
let {min, max} = this.getSlideBoundaries(this.slide, ev);
|
||||||
this.slide.min = min;
|
this.slide.min = min;
|
||||||
this.slide.max = max;
|
this.slide.max = max;
|
||||||
this.slide.elementStartPos = this.getElementStartPos(this.slide, ev);
|
this.slide.elementStartPos = this.getElementStartPos(this.slide, ev);
|
||||||
this.slide.pos = this.slide.pointerStartPos = coord[this.direction];
|
|
||||||
this.slide.timestamp = Date.now();
|
|
||||||
this.slide.started = true;
|
|
||||||
this.slide.velocity = 0;
|
|
||||||
this.onSlideStart(this.slide, ev);
|
this.onSlideStart(this.slide, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
onDragMove(ev: any) {
|
onDragMove(ev: any) {
|
||||||
let slide = this.slide;
|
let slide: SlideData = this.slide;
|
||||||
let coord = <any>pointerCoord(ev);
|
let coord = <any>pointerCoord(ev);
|
||||||
let newPos = coord[this.direction];
|
let newPos = coord[this.direction];
|
||||||
let newTimestamp = Date.now();
|
let newTimestamp = Date.now();
|
||||||
@ -74,7 +83,7 @@ export class SlideGesture extends PanGesture {
|
|||||||
this.slide = null;
|
this.slide = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSlideBeforeStart(slide?: SlideData, ev?: any): void {}
|
onSlideBeforeStart(ev?: any): void {}
|
||||||
onSlideStart(slide?: SlideData, ev?: any): void {}
|
onSlideStart(slide?: SlideData, ev?: any): void {}
|
||||||
onSlide(slide?: SlideData, ev?: any): void {}
|
onSlide(slide?: SlideData, ev?: any): void {}
|
||||||
onSlideEnd(slide?: SlideData, ev?: any): void {}
|
onSlideEnd(slide?: SlideData, ev?: any): void {}
|
||||||
@ -84,14 +93,14 @@ export class SlideGesture extends PanGesture {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
export interface SlideData {
|
export interface SlideData {
|
||||||
min?: number;
|
min: number;
|
||||||
max?: number;
|
max: number;
|
||||||
distance?: number;
|
distance: number;
|
||||||
delta?: number;
|
delta: number;
|
||||||
started?: boolean;
|
started: boolean;
|
||||||
pos?: any;
|
pos: any;
|
||||||
timestamp?: number;
|
timestamp: number;
|
||||||
pointerStartPos?: number;
|
pointerStartPos: number;
|
||||||
elementStartPos?: number;
|
elementStartPos: number;
|
||||||
velocity?: number;
|
velocity: number;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ export class SwipeBackGesture extends SlideEdgeGesture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
onSlideBeforeStart(slideData: SlideData, ev: any) {
|
onSlideBeforeStart(ev: any) {
|
||||||
console.debug('swipeBack, onSlideBeforeStart', ev.type);
|
console.debug('swipeBack, onSlideBeforeStart', ev.type);
|
||||||
this._nav.swipeBackStart();
|
this._nav.swipeBackStart();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user