mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
feat(aside): reveal/overlay aside using Animation
This commit is contained in:
@@ -39,7 +39,7 @@ export class IonicApp {
|
||||
*/
|
||||
constructor() {
|
||||
this.overlays = [];
|
||||
this._isTransitioning = false;
|
||||
this._transTime = 0;
|
||||
|
||||
// Our component registry map
|
||||
this.components = {};
|
||||
@@ -82,7 +82,7 @@ export class IonicApp {
|
||||
* @param {bool} isTransitioning
|
||||
*/
|
||||
setTransitioning(isTransitioning) {
|
||||
this._isTransitioning = !!isTransitioning;
|
||||
this._transTime = (isTransitioning ? Date.now() : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +90,7 @@ export class IonicApp {
|
||||
* @return {bool}
|
||||
*/
|
||||
isTransitioning() {
|
||||
return this._isTransitioning;
|
||||
return (this._transTime + 800 > Date.now());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,6 +33,5 @@ export class AsideToggle {
|
||||
*/
|
||||
toggle(event) {
|
||||
this.aside && this.aside.toggle();
|
||||
console.log('Aside toggle');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,155 +2,56 @@
|
||||
// Aside
|
||||
// --------------------------------------------------
|
||||
|
||||
$aside-width: 304px !default;
|
||||
$aside-small-width: $aside-width - 40px !default;
|
||||
$aside-width: 304px !default;
|
||||
$aside-small-width: $aside-width - 40px !default;
|
||||
|
||||
$aside-transition: 0.2s ease transform !default;
|
||||
$aside-backdrop-transition: 0.2s ease background-color !default;
|
||||
$aside-background: $background-color !default;
|
||||
$aside-shadow: -1px 0px 8px rgba(0, 0, 0, 0.2) !default;
|
||||
$aside-background: $background-color !default;
|
||||
$aside-shadow: 0px 0px 10px rgba(0, 0, 0, 0.25) !default;
|
||||
|
||||
|
||||
.aside {
|
||||
ion-aside {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: auto;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
left: -$aside-width;
|
||||
width: $aside-width;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
background: $aside-background;
|
||||
|
||||
transform: translate3d(0, 0, 0);
|
||||
transition: $aside-transition;
|
||||
|
||||
&.no-transition {
|
||||
ion-aside-backdrop {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&[type=overlay] {
|
||||
z-index: $z-index-aside-overlay;
|
||||
|
||||
&:not(.open):not(.changing) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&[type=reveal] {
|
||||
left: 0;
|
||||
|
||||
&:not(.open):not(.changing) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.open, {
|
||||
&[type=reveal],
|
||||
&[type=push] {
|
||||
left: 0;
|
||||
}
|
||||
&[type=overlay] {
|
||||
transform: translate3d($aside-width,0,0);
|
||||
box-shadow: 1px 2px 16px rgba(0, 0, 0, 0.3);
|
||||
|
||||
ion-aside-backdrop {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&[side=right] {
|
||||
width: $aside-width;
|
||||
left: 100%;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
|
||||
transform: translate3d(0,0,0);
|
||||
&.open,
|
||||
&[type=reveal] {
|
||||
transform: translate3d(-$aside-width,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
&[side=top] {
|
||||
height: $aside-width;
|
||||
top: -$aside-width;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
transform: translate3d(0,0,0);
|
||||
&.open,
|
||||
&[type=reveal] {
|
||||
transform: translate3d(0,$aside-width,0);
|
||||
}
|
||||
}
|
||||
|
||||
&[side=bottom] {
|
||||
height: $aside-width;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
transform: translate3d(0,0,0);
|
||||
&.open,
|
||||
&.type-reveal {
|
||||
transform: translate3d(0,-$aside-width,0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ion-aside-backdrop {
|
||||
z-index: $z-index-aside-backdrop;
|
||||
transition: $aside-backdrop-transition;
|
||||
transform: translateX($aside-width);
|
||||
top: 0;
|
||||
ion-aside[side=right] {
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
position: fixed;
|
||||
background-color: rgb(0,0,0);
|
||||
left: auto;
|
||||
}
|
||||
|
||||
ion-aside backdrop {
|
||||
z-index: -1;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.aside-content {
|
||||
transition: $aside-transition;
|
||||
transform: translate3d(0,0,0);
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
}
|
||||
|
||||
box-shadow: $aside-shadow;
|
||||
&.aside-open-left {
|
||||
transform: translate3d($aside-width,0,0);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&.aside-open-right {
|
||||
transform: translate3d(-$aside-width,0,0);
|
||||
pointer-events: none;
|
||||
}
|
||||
.aside-content-open ion-pane,
|
||||
.aside-content-open ion-content,
|
||||
.aside-content-open .toolbar {
|
||||
// the containing element itself should be clickable but
|
||||
// everything inside of it should not clickable when aside is open
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 340px) {
|
||||
|
||||
.aside {
|
||||
left: -$aside-small-width;
|
||||
ion-aside {
|
||||
width: $aside-small-width;
|
||||
}
|
||||
|
||||
.aside-content {
|
||||
&.aside-open-left {
|
||||
transform: translate3d($aside-small-width, 0, 0);
|
||||
}
|
||||
|
||||
&.aside-open-right {
|
||||
transform: translate3d(-$aside-small-width, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import {forwardRef, Component, Host, View, EventEmitter, ElementRef} from 'angular2/angular2';
|
||||
import {forwardRef, Directive, Host, View, EventEmitter, ElementRef} from 'angular2/angular2';
|
||||
|
||||
import {Ion} from '../ion';
|
||||
import {IonicApp} from '../app/app';
|
||||
import {IonicConfig} from '../../config/config';
|
||||
import {IonicComponent} from '../../config/annotations';
|
||||
import * as types from './extensions/types'
|
||||
import * as gestures from './extensions/gestures'
|
||||
import * as util from 'ionic/util/util'
|
||||
import {dom} from 'ionic/util'
|
||||
import * as gestures from './extensions/gestures';
|
||||
|
||||
|
||||
/**
|
||||
* Aside is a side-menu navigation that can be dragged out or toggled to show. Aside supports two
|
||||
@@ -25,152 +23,74 @@ import {dom} from 'ionic/util'
|
||||
'side': 'left',
|
||||
'type': 'reveal'
|
||||
},
|
||||
delegates: {
|
||||
gesture: [
|
||||
//[instance => instance.side == 'top', gestures.TopAsideGesture],
|
||||
//[instance => instance.side == 'bottom', gestures.BottomAsideGesture],
|
||||
[instance => instance.side == 'right', gestures.RightAsideGesture],
|
||||
[instance => instance.side == 'left', gestures.LeftAsideGesture],
|
||||
],
|
||||
type: [
|
||||
[instance => instance.type == 'overlay', types.AsideTypeOverlay],
|
||||
[instance => instance.type == 'reveal', types.AsideTypeReveal],
|
||||
//[instance => instance.type == 'push', types.AsideTypePush],
|
||||
]
|
||||
},
|
||||
events: ['opening']
|
||||
})
|
||||
@View({
|
||||
template: '<ng-content></ng-content><ion-aside-backdrop></ion-aside-backdrop>',
|
||||
template: '<ng-content></ng-content><backdrop tappable></backdrop>',
|
||||
directives: [forwardRef(() => AsideBackdrop)]
|
||||
})
|
||||
export class Aside extends Ion {
|
||||
/**
|
||||
* TODO
|
||||
* @param {IonicApp} app TODO
|
||||
* @param {ElementRef} elementRef Reference to the element.
|
||||
*/
|
||||
|
||||
constructor(app: IonicApp, elementRef: ElementRef, config: IonicConfig) {
|
||||
super(elementRef, config);
|
||||
|
||||
this.app = app;
|
||||
|
||||
this.opening = new EventEmitter('opening');
|
||||
|
||||
//this.animation = new Animation(element.querySelector('backdrop'));
|
||||
this.contentClickFn = (e) => {
|
||||
if(!this.isOpen || this.isChanging) { return; }
|
||||
this.close();
|
||||
};
|
||||
|
||||
|
||||
this.finishChanging = util.debounce(() => {
|
||||
this.setChanging(false);
|
||||
});
|
||||
|
||||
// TODO: Use Animation Class
|
||||
this.getNativeElement().addEventListener('transitionend', ev => {
|
||||
//this.setChanging(false)
|
||||
clearTimeout(this.setChangeTimeout);
|
||||
this.setChangeTimeout = setInterval(this.finishChanging, 400);
|
||||
})
|
||||
this.isOpen = false;
|
||||
this._disableTime = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
onDestroy() {
|
||||
app.unregister(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
onInit() {
|
||||
super.onInit();
|
||||
this.contentElement = (this.content instanceof Node) ? this.content : this.content.getNativeElement();
|
||||
|
||||
if(!this.id) {
|
||||
if (!this.contentElement) {
|
||||
return console.error('Aside: must have a [content] element to listen for drag events on. Example:\n\n<ion-aside [content]="content"></ion-aside>\n\n<ion-content #content></ion-content>');
|
||||
}
|
||||
|
||||
if (!this.id) {
|
||||
// Auto register
|
||||
this.app.register('menu', this);
|
||||
}
|
||||
|
||||
if(this.contentElement) {
|
||||
this.contentElement.addEventListener('transitionend', ev => {
|
||||
//this.setChanging(false)
|
||||
clearTimeout(this.setChangeTimeout);
|
||||
this.setChangeTimeout = setInterval(this.finishChanging, 400);
|
||||
})
|
||||
this.contentElement.addEventListener('click', this.contentClickFn);
|
||||
} else {
|
||||
console.error('Aside: must have a [content] element to listen for drag events on. Supply one like this:\n\n<ion-aside [content]="content"></ion-aside>\n\n<ion-content #content>');
|
||||
}
|
||||
this._initGesture();
|
||||
this._initType(this.type);
|
||||
|
||||
this.contentElement.classList.add('aside-content');
|
||||
this.contentElement.classList.add('aside-content-' + this.type);
|
||||
|
||||
this.gestureDelegate = this.getDelegate('gesture');
|
||||
this.typeDelegate = this.getDelegate('type');
|
||||
let self = this;
|
||||
this.onContentClick = function(ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
self.close();
|
||||
};
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
this.contentElement.removeEventListener('click', this.contentClickFn);
|
||||
}
|
||||
_initGesture() {
|
||||
switch(this.side) {
|
||||
case 'right':
|
||||
this._gesture = new gestures.RightAsideGesture(this);
|
||||
break;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @return {Element} The Aside's content element.
|
||||
*/
|
||||
getContentElement() {
|
||||
return this.contentElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @param {TODO} v TODO
|
||||
*/
|
||||
setOpenAmt(v) {
|
||||
this.opening.next(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @param {boolean} willOpen TODO
|
||||
*/
|
||||
setDoneTransforming(willOpen) {
|
||||
this.typeDelegate.setDoneTransforming(willOpen);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @param {TODO} transform TODO
|
||||
*/
|
||||
setTransform(transform) {
|
||||
this.typeDelegate.setTransform(transform)
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @param {boolean} isSliding TODO
|
||||
*/
|
||||
setSliding(isSliding) {
|
||||
if (isSliding !== this.isSliding) {
|
||||
this.typeDelegate.setSliding(isSliding)
|
||||
case 'left':
|
||||
this._gesture = new gestures.LeftAsideGesture(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @param {boolean} isChanging TODO
|
||||
*/
|
||||
setChanging(isChanging) {
|
||||
_initType(type) {
|
||||
type = type && type.trim().toLowerCase() || FALLBACK_ASIDE_TYPE;
|
||||
|
||||
// Stop any last changing end operations
|
||||
clearTimeout(this.setChangeTimeout);
|
||||
|
||||
if (isChanging !== this.isChanging) {
|
||||
this.isChanging = isChanging
|
||||
this.getNativeElement().classList[isChanging ? 'add' : 'remove']('changing');
|
||||
let asideTypeCls = asideTypes[type];
|
||||
|
||||
if (!asideTypeCls) {
|
||||
type = FALLBACK_ASIDE_TYPE;
|
||||
asideTypeCls = asideTypes[type];
|
||||
}
|
||||
|
||||
this._type = new asideTypeCls(this);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,18 +98,79 @@ export class Aside extends Ion {
|
||||
* @param {boolean} isOpen If the Aside is open or not.
|
||||
* @return {Promise} TODO
|
||||
*/
|
||||
setOpen(isOpen) {
|
||||
if (isOpen !== this.isOpen) {
|
||||
this.isOpen = isOpen;
|
||||
this.setChanging(true);
|
||||
|
||||
// Set full or closed amount
|
||||
this.setOpenAmt(isOpen ? 1 : 0);
|
||||
|
||||
return dom.rafPromise().then(() => {
|
||||
this.typeDelegate.setOpen(isOpen)
|
||||
})
|
||||
setOpen(shouldOpen) {
|
||||
// _isDisabled is used to prevent unwanted opening/closing after swiping open/close
|
||||
// or swiping open the menu while pressing down on the aside-toggle button
|
||||
if (shouldOpen === this.isOpen || this._isDisabled()) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
this._before();
|
||||
|
||||
return this._type.setOpen(shouldOpen).then(() => {
|
||||
this._after(shouldOpen);
|
||||
});
|
||||
}
|
||||
|
||||
setProgressStart() {
|
||||
// user started swiping the aside open/close
|
||||
if (this._isDisabled()) return;
|
||||
|
||||
this._before();
|
||||
|
||||
this._type.setProgressStart(this.isOpen);
|
||||
}
|
||||
|
||||
setProgess(value) {
|
||||
// user actively dragging the menu
|
||||
this._disable();
|
||||
this._type.setProgess(value);
|
||||
}
|
||||
|
||||
setProgressFinish(shouldComplete) {
|
||||
// user has finished dragging the menu
|
||||
this._disable();
|
||||
this._type.setProgressFinish(shouldComplete).then(isOpen => {
|
||||
this._after(isOpen);
|
||||
});
|
||||
}
|
||||
|
||||
_before() {
|
||||
// this places the aside into the correct location before it animates in
|
||||
// this css class doesn't actually kick off any animations
|
||||
this.getNativeElement().classList.add('show-aside');
|
||||
this.getBackdropElement().classList.add('show-backdrop');
|
||||
|
||||
this._disable();
|
||||
this.app.setTransitioning(true);
|
||||
}
|
||||
|
||||
_after(isOpen) {
|
||||
this._disable();
|
||||
this.isOpen = isOpen;
|
||||
|
||||
this.contentElement.classList[isOpen ? 'add' : 'remove']('aside-content-open');
|
||||
|
||||
this.contentElement.removeEventListener('click', this.onContentClick);
|
||||
if (isOpen) {
|
||||
this.contentElement.addEventListener('click', this.onContentClick);
|
||||
|
||||
} else {
|
||||
this.getNativeElement().classList.remove('show-aside');
|
||||
this.getBackdropElement().classList.remove('show-backdrop');
|
||||
}
|
||||
|
||||
this.app.setTransitioning(false);
|
||||
}
|
||||
|
||||
_disable() {
|
||||
// used to prevent unwanted opening/closing after swiping open/close
|
||||
// or swiping open the menu while pressing down on the aside-toggle
|
||||
this._disableTime = Date.now();
|
||||
}
|
||||
|
||||
_isDisabled() {
|
||||
return this._disableTime + 300 > Date.now();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -216,55 +197,75 @@ export class Aside extends Ion {
|
||||
return this.setOpen(!this.isOpen);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @return {Element} The Aside element.
|
||||
*/
|
||||
getAsideElement() {
|
||||
return this.getNativeElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @return {Element} The Aside's associated content element.
|
||||
*/
|
||||
getContentElement() {
|
||||
return this.contentElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @return {Element} The Aside's associated content element.
|
||||
*/
|
||||
getBackdropElement() {
|
||||
return this.backdrop.elementRef.nativeElement;
|
||||
}
|
||||
|
||||
static register(name, cls) {
|
||||
asideTypes[name] = cls;
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
this.app.unregister(this);
|
||||
this._type && this._type.onDestroy();
|
||||
this.contentElement = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let asideTypes = {};
|
||||
const FALLBACK_ASIDE_TYPE = 'reveal';
|
||||
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ion-aside-backdrop',
|
||||
@Directive({
|
||||
selector: 'backdrop',
|
||||
host: {
|
||||
'[style.width]': 'width',
|
||||
'[style.height]': 'height',
|
||||
'[style.opacity]': 'opacity',
|
||||
'(click)': 'clicked($event)'
|
||||
}
|
||||
})
|
||||
@View({
|
||||
template: ''
|
||||
})
|
||||
export class AsideBackdrop extends Ion {
|
||||
class AsideBackdrop {
|
||||
/**
|
||||
* TODO
|
||||
* @param {ElementReg} elementRef TODO
|
||||
* @param {IonicConfig} config TODO
|
||||
* @param {Aside} aside TODO
|
||||
*/
|
||||
constructor(elementRef: ElementRef, config: IonicConfig, @Host() aside: Aside) {
|
||||
super(elementRef, config);
|
||||
|
||||
aside.backdrop = this;
|
||||
|
||||
constructor(@Host() aside: Aside, elementRef: ElementRef) {
|
||||
this.aside = aside;
|
||||
|
||||
this.opacity = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
onInit() {
|
||||
let ww = window.innerWidth;
|
||||
let wh = window.innerHeight;
|
||||
this.width = ww + 'px';
|
||||
this.height = wh + 'px';
|
||||
this.elementRef = elementRef;
|
||||
aside.backdrop = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @param {TODO} event TODO
|
||||
*/
|
||||
clicked(event) {
|
||||
clicked(ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
this.aside.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,47 +1,37 @@
|
||||
import {Aside} from 'ionic/components/aside/aside';
|
||||
//TODO: figure out way to get rid of all the ../../../../
|
||||
import {Aside} from '../aside';
|
||||
import {SlideEdgeGesture} from 'ionic/gestures/slide-edge-gesture';
|
||||
|
||||
class AsideTargetGesture extends SlideEdgeGesture {
|
||||
constructor(aside: Aside) {
|
||||
let asideElement = aside.getNativeElement();
|
||||
super(asideElement, {
|
||||
|
||||
class AsideGenericGestureHandler extends SlideEdgeGesture {
|
||||
constructor(aside: Aside, targetElement, threshold) {
|
||||
super(targetElement, {
|
||||
direction: (aside.side === 'left' || aside.side === 'right') ? 'x' : 'y',
|
||||
edge: aside.side,
|
||||
threshold: 0
|
||||
threshold: threshold
|
||||
});
|
||||
|
||||
this.aside = aside;
|
||||
this.listen();
|
||||
}
|
||||
canStart(ev) {
|
||||
return this.aside.isOpen;
|
||||
}
|
||||
|
||||
// Set CSS, then wait one frame for it to apply before sliding starts
|
||||
onSlideBeforeStart(slide, ev) {
|
||||
this.aside.setSliding(true);
|
||||
this.aside.setChanging(true);
|
||||
return new Promise(resolve => {
|
||||
requestAnimationFrame(resolve);
|
||||
});
|
||||
this.aside.setProgressStart();
|
||||
}
|
||||
|
||||
onSlide(slide, ev) {
|
||||
this.aside.setOpenAmt(slide.distance / slide.max);
|
||||
this.aside.setTransform(slide.distance);
|
||||
this.aside.setProgess(slide.distance / slide.max);
|
||||
}
|
||||
|
||||
onSlideEnd(slide, ev) {
|
||||
this.aside.setSliding(false);
|
||||
if (Math.abs(ev.velocityX) > 0.2 || Math.abs(slide.delta) > Math.abs(slide.max) * 0.5) {
|
||||
|
||||
this.aside.setOpen(!this.aside.isOpen);
|
||||
this.aside.setDoneTransforming(!this.aside.isOpen);
|
||||
|
||||
} else {
|
||||
this.aside.setDoneTransforming(this.aside.isOpen);
|
||||
}
|
||||
let shouldComplete = (Math.abs(ev.velocityX) > 0.2 || Math.abs(slide.delta) > Math.abs(slide.max) * 0.5);
|
||||
this.aside.setProgressFinish(shouldComplete);
|
||||
}
|
||||
|
||||
getElementStartPos(slide, ev) {
|
||||
return this.aside.isOpen ? slide.max : slide.min;
|
||||
}
|
||||
|
||||
getSlideBoundaries() {
|
||||
return {
|
||||
min: 0,
|
||||
@@ -50,64 +40,26 @@ class AsideTargetGesture extends SlideEdgeGesture {
|
||||
}
|
||||
}
|
||||
|
||||
class AsideGesture extends SlideEdgeGesture {
|
||||
|
||||
export class AsideContentGesture extends AsideGenericGestureHandler {
|
||||
constructor(aside: Aside) {
|
||||
// TODO figure out the sliding element, dont just use the parent
|
||||
let contentElement = aside.getContentElement();
|
||||
super(contentElement, {
|
||||
direction: (aside.side === 'left' || aside.side === 'right') ? 'x' : 'y',
|
||||
edge: aside.side,
|
||||
threshold: 75
|
||||
});
|
||||
this.aside = aside;
|
||||
this.slideElement = contentElement;
|
||||
this.listen();
|
||||
|
||||
let contentGesture = new AsideTargetGesture(aside);
|
||||
contentGesture.listen();
|
||||
super(aside, aside.getContentElement(), 75);
|
||||
}
|
||||
|
||||
canStart(ev) {
|
||||
// Only restrict edges if the aside is closed
|
||||
return this.aside.isOpen ? true : super.canStart(ev);
|
||||
}
|
||||
}
|
||||
|
||||
// Set CSS, then wait one frame for it to apply before sliding starts
|
||||
onSlideBeforeStart(slide, ev) {
|
||||
this.aside.setSliding(true);
|
||||
this.aside.setChanging(true);
|
||||
return new Promise(resolve => {
|
||||
requestAnimationFrame(resolve);
|
||||
});
|
||||
}
|
||||
onSlide(slide, ev) {
|
||||
this.aside.setOpenAmt(slide.distance / slide.max);
|
||||
this.aside.setTransform(slide.distance);
|
||||
}
|
||||
onSlideEnd(slide, ev) {
|
||||
this.aside.setSliding(false);
|
||||
if (Math.abs(ev.velocityX) > 0.2 || Math.abs(slide.delta) > Math.abs(slide.max) * 0.5) {
|
||||
this.aside.setOpen(!this.aside.isOpen);
|
||||
this.aside.setDoneTransforming(!this.aside.isOpen);
|
||||
} else {
|
||||
this.aside.setDoneTransforming(false);
|
||||
}
|
||||
}
|
||||
|
||||
getElementStartPos(slide, ev) {
|
||||
return this.aside.isOpen ? slide.max : slide.min;
|
||||
}
|
||||
getSlideBoundaries() {
|
||||
return {
|
||||
min: 0,
|
||||
max: this.aside.width()
|
||||
};
|
||||
export class LeftAsideGesture extends AsideContentGesture {
|
||||
constructor(aside: Aside) {
|
||||
super(aside);
|
||||
}
|
||||
}
|
||||
|
||||
export class LeftAsideGesture extends AsideGesture {}
|
||||
|
||||
export class RightAsideGesture extends LeftAsideGesture {
|
||||
constructor(aside: Aside) {
|
||||
super(aside);
|
||||
}
|
||||
getElementStartPos(slide, ev) {
|
||||
return this.aside.isOpen ? slide.min : slide.max;
|
||||
}
|
||||
|
||||
41
ionic/components/aside/extensions/types.scss
Normal file
41
ionic/components/aside/extensions/types.scss
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
// Aside Reveal
|
||||
// --------------------------------------------------
|
||||
// The content slides over to reveal the aside underneath.
|
||||
// The aside menu itself, which is under the content, does not move.
|
||||
|
||||
ion-aside[type=reveal] {
|
||||
transform: translate3d(-9999px, 0px, 0px);
|
||||
|
||||
&.show-aside {
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
}
|
||||
}
|
||||
|
||||
.aside-content-reveal {
|
||||
box-shadow: $aside-shadow;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Aside Overlay
|
||||
// --------------------------------------------------
|
||||
// The aside menu slides over the content. The content
|
||||
// itself, which is under the aside, does not move.
|
||||
|
||||
ion-aside[type=overlay] {
|
||||
z-index: $z-index-aside-overlay;
|
||||
box-shadow: $aside-shadow;
|
||||
transform: translate3d(-9999px, 0px, 0px);
|
||||
|
||||
backdrop {
|
||||
display: block;
|
||||
transform: translate3d(-9999px, 0px, 0px);
|
||||
opacity: 0.01;
|
||||
width: 3000px;
|
||||
|
||||
&.show-backdrop {
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,124 +1,147 @@
|
||||
import {Aside} from 'ionic/components/aside/aside';
|
||||
import {Animtion} from 'ionic/aside/aside';
|
||||
import {CSS} from 'ionic/util/dom'
|
||||
import {Aside} from '../aside';
|
||||
import {Animation} from 'ionic/animations/animation';
|
||||
|
||||
// TODO use setters instead of direct dom manipulation
|
||||
const asideManipulator = {
|
||||
setSliding(sliding) {
|
||||
this.aside.getNativeElement().classList[sliding ? 'add' : 'remove']('no-transition');
|
||||
},
|
||||
setOpen(open) {
|
||||
this.aside.getNativeElement().classList[open ? 'add' : 'remove']('open');
|
||||
},
|
||||
setTransform(t) {
|
||||
if(t === null) {
|
||||
this.aside.getNativeElement().style[CSS.transform] = '';
|
||||
} else {
|
||||
this.aside.getNativeElement().style[CSS.transform] = 'translate3d(' + t + 'px,0,0)';
|
||||
}
|
||||
}
|
||||
}
|
||||
const contentManipulator = {
|
||||
setSliding(sliding) {
|
||||
this.aside.contentElement.classList[sliding ? 'add' : 'remove']('no-transition');
|
||||
},
|
||||
setOpen(open) {
|
||||
this.aside.contentElement.classList[open ? 'add' : 'remove'](
|
||||
`aside-open-${this.aside.side}`
|
||||
)
|
||||
},
|
||||
setTransform(t) {
|
||||
if(t === null) {
|
||||
this.aside.contentElement.style[CSS.transform] = '';
|
||||
} else {
|
||||
this.aside.contentElement.style[CSS.transform] = 'translate3d(' + t + 'px,0,0)';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const backdropManipulator = {
|
||||
setSliding(sliding) {
|
||||
this.aside.backdrop.isTransitioning = sliding;
|
||||
//.classList[sliding ? 'add' : 'remove']('no-transition');
|
||||
},
|
||||
setOpen(open) {
|
||||
let amt = open ? 0.5 : 0;
|
||||
this.aside.backdrop.opacity = amt;
|
||||
},
|
||||
setTransform(t) {
|
||||
if(t === null) {
|
||||
t = this.aside.width();
|
||||
}
|
||||
let fade = 0.5 * t / this.aside.width();
|
||||
this.aside.backdrop.opacity = fade;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Aside Type
|
||||
* Base class which is extended by the various types. Each
|
||||
* type will provide their own animations for open and close
|
||||
* and registers itself with Aside.
|
||||
*/
|
||||
export class AsideType {
|
||||
|
||||
constructor(aside: Aside) {
|
||||
this.aside = aside;
|
||||
|
||||
setTimeout(() => {
|
||||
aside.contentElement.classList.add('aside-content')
|
||||
})
|
||||
this.open = new Animation();
|
||||
this.close = new Animation();
|
||||
}
|
||||
|
||||
setOpen(shouldOpen) {
|
||||
return new Promise(resolve => {
|
||||
if (shouldOpen) {
|
||||
this.open.playbackRate(1).onFinish(resolve, true).play();
|
||||
} else {
|
||||
this.close.playbackRate(1).onFinish(resolve, true).play();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setProgressStart(isOpen) {
|
||||
this.isOpening = !isOpen;
|
||||
|
||||
this.seek && this.seek.dispose();
|
||||
|
||||
// clone the correct animation depending on open/close
|
||||
if (this.isOpening) {
|
||||
this.seek = this.open.clone();
|
||||
} else {
|
||||
this.seek = this.close.clone();
|
||||
}
|
||||
|
||||
// the cloned animation should not use an easing curve during seek
|
||||
this.seek.easing('linear').progressStart();
|
||||
}
|
||||
|
||||
setProgess(value) {
|
||||
// adjust progress value depending if it opening or closing
|
||||
if (!this.isOpening) {
|
||||
value = 1 - value;
|
||||
}
|
||||
this.seek.progress(value);
|
||||
}
|
||||
|
||||
setProgressFinish(shouldComplete) {
|
||||
let resolve;
|
||||
let promise = new Promise(res => { resolve = res });
|
||||
|
||||
let isOpen = (this.isOpening && shouldComplete);
|
||||
if (!this.isOpening && !shouldComplete) {
|
||||
isOpen = true;
|
||||
}
|
||||
|
||||
this.seek.progressFinish(shouldComplete).then(() => {
|
||||
this.isOpening = false;
|
||||
resolve(isOpen);
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
onDestory() {
|
||||
this.open && this.open.dispose();
|
||||
this.close && this.close.dispose();
|
||||
this.seek && this.seek.dispose();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class AsideTypeOverlay extends AsideType {
|
||||
setSliding(sliding) {
|
||||
asideManipulator.setSliding.call(this, sliding);
|
||||
backdropManipulator.setSliding.call(this, sliding);
|
||||
}
|
||||
setOpen(open) {
|
||||
asideManipulator.setOpen.call(this, open);
|
||||
backdropManipulator.setOpen.call(this, open);
|
||||
}
|
||||
setTransform(t) {
|
||||
asideManipulator.setTransform.call(this, t);
|
||||
backdropManipulator.setTransform.call(this, t);
|
||||
}
|
||||
setDoneTransforming(willOpen) {
|
||||
asideManipulator.setTransform.call(this, null);
|
||||
backdropManipulator.setTransform.call(this, null);
|
||||
asideManipulator.setOpen.call(this, willOpen);
|
||||
backdropManipulator.setOpen.call(this, willOpen);
|
||||
}
|
||||
}
|
||||
|
||||
export class AsideTypePush extends AsideType {
|
||||
setSliding(sliding) {
|
||||
asideManipulator.setSliding.call(this, sliding);
|
||||
contentManipulator.setSliding.call(this, sliding);
|
||||
}
|
||||
setOpen(open) {
|
||||
asideManipulator.setOpen.call(this, open);
|
||||
contentManipulator.setOpen.call(this, open);
|
||||
}
|
||||
setTransform(t) {
|
||||
asideManipulator.setTransform.call(this, t);
|
||||
contentManipulator.setTransform.call(this, t);
|
||||
}
|
||||
setDoneTransforming(willOpen) {
|
||||
asideManipulator.setOpen.call(this, willOpen);
|
||||
asideManipulator.setTransform.call(this, null);
|
||||
contentManipulator.setOpen.call(this, willOpen);
|
||||
contentManipulator.setTransform.call(this, null);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Aside Reveal Type
|
||||
* The content slides over to reveal the aside underneath.
|
||||
* The aside menu itself, which is under the content, does not move.
|
||||
*/
|
||||
class AsideRevealType extends AsideType {
|
||||
constructor(aside) {
|
||||
super();
|
||||
|
||||
export class AsideTypeReveal extends AsideType {
|
||||
setSliding(sliding) {
|
||||
contentManipulator.setSliding.call(this, sliding);
|
||||
}
|
||||
setOpen(sliding) {
|
||||
asideManipulator.setOpen.call(this, sliding);
|
||||
contentManipulator.setOpen.call(this, sliding);
|
||||
}
|
||||
setTransform(t) {
|
||||
contentManipulator.setTransform.call(this, t);
|
||||
}
|
||||
setDoneTransforming(willOpen) {
|
||||
contentManipulator.setOpen.call(this, willOpen);
|
||||
contentManipulator.setTransform.call(this, null);
|
||||
let easing = 'ease';
|
||||
let duration = 250;
|
||||
|
||||
let openedX = (aside.width() * (aside.side == 'right' ? -1 : 1)) + 'px';
|
||||
|
||||
this.open.easing(easing).duration(duration);
|
||||
this.close.easing(easing).duration(duration);
|
||||
|
||||
let contentOpen = new Animation(aside.getContentElement());
|
||||
contentOpen.fromTo(TRANSLATE_X, CENTER, openedX);
|
||||
this.open.add(contentOpen);
|
||||
|
||||
let contentClose = new Animation(aside.getContentElement());
|
||||
contentClose.fromTo(TRANSLATE_X, openedX, CENTER);
|
||||
this.close.add(contentClose);
|
||||
}
|
||||
}
|
||||
Aside.register('reveal', AsideRevealType);
|
||||
|
||||
|
||||
/**
|
||||
* Aside Overlay Type
|
||||
* The aside menu slides over the content. The content
|
||||
* itself, which is under the aside, does not move.
|
||||
*/
|
||||
class AsideOverlayType extends AsideType {
|
||||
constructor(aside) {
|
||||
super();
|
||||
|
||||
let easing = 'ease';
|
||||
let duration = 250;
|
||||
let backdropOpacity = 0.5;
|
||||
|
||||
let closedX = (aside.width() * (aside.side == 'right' ? 1 : -1)) + 'px';
|
||||
|
||||
this.open.easing(easing).duration(duration);
|
||||
this.close.easing(easing).duration(duration);
|
||||
|
||||
let asideOpen = new Animation(aside.getAsideElement());
|
||||
asideOpen.fromTo(TRANSLATE_X, closedX, CENTER);
|
||||
this.open.add(asideOpen);
|
||||
|
||||
let backdropOpen = new Animation(aside.getBackdropElement());
|
||||
backdropOpen.fromTo(OPACITY, 0.01, backdropOpacity);
|
||||
this.open.add(backdropOpen);
|
||||
|
||||
let asideClose = new Animation(aside.getAsideElement());
|
||||
asideClose.fromTo(TRANSLATE_X, CENTER, closedX);
|
||||
this.close.add(asideClose);
|
||||
|
||||
let backdropClose = new Animation(aside.getBackdropElement());
|
||||
backdropClose.fromTo(OPACITY, backdropOpacity, 0.01);
|
||||
this.close.add(backdropClose);
|
||||
}
|
||||
}
|
||||
Aside.register('overlay', AsideOverlayType);
|
||||
|
||||
|
||||
const OPACITY = 'opacity';
|
||||
const TRANSLATE_X = 'translateX';
|
||||
const CENTER = '0px';
|
||||
|
||||
@@ -20,6 +20,6 @@
|
||||
<button id="e2eContentToggleAside" aside-toggle>Toggle Aside</button>
|
||||
</p>
|
||||
|
||||
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
|
||||
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
|
||||
|
||||
</ion-content>
|
||||
|
||||
27
ionic/components/aside/test/overlay/index.ts
Normal file
27
ionic/components/aside/test/overlay/index.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import {App, IonicApp, IonicView} from 'ionic/ionic';
|
||||
|
||||
|
||||
@IonicView({templateUrl: 'page1.html'})
|
||||
class Page1 {}
|
||||
|
||||
|
||||
@App({
|
||||
templateUrl: 'main.html'
|
||||
})
|
||||
class E2EApp {
|
||||
|
||||
constructor(app: IonicApp) {
|
||||
this.app = app;
|
||||
this.rootView = Page1;
|
||||
}
|
||||
|
||||
openPage(aside, page) {
|
||||
// close the menu when clicking a link from the aside
|
||||
aside.close();
|
||||
|
||||
// Reset the content nav to have just this page
|
||||
// we wouldn't want the back button to show in this scenario
|
||||
let nav = this.app.getComponent('nav');
|
||||
nav.setRoot(page.component);
|
||||
}
|
||||
}
|
||||
41
ionic/components/aside/test/overlay/main.html
Normal file
41
ionic/components/aside/test/overlay/main.html
Normal file
@@ -0,0 +1,41 @@
|
||||
<ion-aside [content]="content" id="leftMenu" type="overlay" side="left">
|
||||
|
||||
<ion-toolbar secondary>
|
||||
<ion-title>Left Menu</ion-title>
|
||||
</ion-toolbar>
|
||||
|
||||
<ion-content>
|
||||
|
||||
<ion-list>
|
||||
|
||||
<button ion-item aside-toggle="leftMenu">
|
||||
Close Left Menu
|
||||
</button>
|
||||
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
|
||||
</ion-aside>
|
||||
|
||||
|
||||
<!-- <ion-aside [content]="content" id="rightMenu" type="reveal" side="right">
|
||||
|
||||
<ion-toolbar secondary>
|
||||
<ion-title>Right Menu</ion-title>
|
||||
</ion-toolbar>
|
||||
|
||||
<ion-content>
|
||||
|
||||
<ion-list>
|
||||
|
||||
<button ion-item aside-toggle="rightMenu">
|
||||
Close Right Menu
|
||||
</button>
|
||||
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
|
||||
</ion-aside> -->
|
||||
|
||||
|
||||
<ion-nav id="nav" [root]="rootView" #content swipe-back-enabled="false"></ion-nav>
|
||||
29
ionic/components/aside/test/overlay/page1.html
Normal file
29
ionic/components/aside/test/overlay/page1.html
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
<ion-navbar *navbar>
|
||||
|
||||
<button aside-toggle="leftMenu">
|
||||
<icon menu></icon>
|
||||
</button>
|
||||
|
||||
<ion-title>
|
||||
Overlay Aside
|
||||
</ion-title>
|
||||
|
||||
</ion-navbar>
|
||||
|
||||
|
||||
<ion-content #content padding>
|
||||
|
||||
<h3>Content</h3>
|
||||
|
||||
<p>
|
||||
<button aside-toggle="leftMenu">Toggle Left Aside</button>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<button aside-toggle="rightMenu">Toggle Right Aside</button>
|
||||
</p>
|
||||
|
||||
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
|
||||
|
||||
</ion-content>
|
||||
27
ionic/components/aside/test/reveal/index.ts
Normal file
27
ionic/components/aside/test/reveal/index.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import {App, IonicApp, IonicView} from 'ionic/ionic';
|
||||
|
||||
|
||||
@IonicView({templateUrl: 'page1.html'})
|
||||
class Page1 {}
|
||||
|
||||
|
||||
@App({
|
||||
templateUrl: 'main.html'
|
||||
})
|
||||
class E2EApp {
|
||||
|
||||
constructor(app: IonicApp) {
|
||||
this.app = app;
|
||||
this.rootView = Page1;
|
||||
}
|
||||
|
||||
openPage(aside, page) {
|
||||
// close the menu when clicking a link from the aside
|
||||
aside.close();
|
||||
|
||||
// Reset the content nav to have just this page
|
||||
// we wouldn't want the back button to show in this scenario
|
||||
let nav = this.app.getComponent('nav');
|
||||
nav.setRoot(page.component);
|
||||
}
|
||||
}
|
||||
41
ionic/components/aside/test/reveal/main.html
Normal file
41
ionic/components/aside/test/reveal/main.html
Normal file
@@ -0,0 +1,41 @@
|
||||
<ion-aside [content]="content" id="leftMenu" type="reveal" side="left">
|
||||
|
||||
<ion-toolbar secondary>
|
||||
<ion-title>Left Menu</ion-title>
|
||||
</ion-toolbar>
|
||||
|
||||
<ion-content>
|
||||
|
||||
<ion-list>
|
||||
|
||||
<button ion-item aside-toggle="leftMenu">
|
||||
Close Left Menu
|
||||
</button>
|
||||
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
|
||||
</ion-aside>
|
||||
|
||||
|
||||
<!-- <ion-aside [content]="content" id="rightMenu" type="reveal" side="right">
|
||||
|
||||
<ion-toolbar secondary>
|
||||
<ion-title>Right Menu</ion-title>
|
||||
</ion-toolbar>
|
||||
|
||||
<ion-content>
|
||||
|
||||
<ion-list>
|
||||
|
||||
<button ion-item aside-toggle="rightMenu">
|
||||
Close Right Menu
|
||||
</button>
|
||||
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
|
||||
</ion-aside> -->
|
||||
|
||||
|
||||
<ion-nav id="nav" [root]="rootView" #content swipe-back-enabled="false"></ion-nav>
|
||||
29
ionic/components/aside/test/reveal/page1.html
Normal file
29
ionic/components/aside/test/reveal/page1.html
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
<ion-navbar *navbar>
|
||||
|
||||
<button aside-toggle="leftMenu">
|
||||
<icon menu></icon>
|
||||
</button>
|
||||
|
||||
<ion-title>
|
||||
Reveal Aside
|
||||
</ion-title>
|
||||
|
||||
</ion-navbar>
|
||||
|
||||
|
||||
<ion-content #content padding>
|
||||
|
||||
<h3>Content</h3>
|
||||
|
||||
<p>
|
||||
<button aside-toggle="leftMenu">Toggle Left Aside</button>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<button aside-toggle="rightMenu">Toggle Right Aside</button>
|
||||
</p>
|
||||
|
||||
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
|
||||
|
||||
</ion-content>
|
||||
@@ -1,4 +1,5 @@
|
||||
import {IonicConfig} from '../config/config';
|
||||
import {Platform} from '../platform/platform';
|
||||
import * as util from 'ionic/util';
|
||||
|
||||
|
||||
@@ -76,11 +77,11 @@ export class Ion {
|
||||
}
|
||||
|
||||
width() {
|
||||
return this.getNativeElement().offsetWidth;
|
||||
return Platform.getDimensions(this).w;
|
||||
}
|
||||
|
||||
height() {
|
||||
return this.getNativeElement().offsetHeight;
|
||||
return Platform.getDimensions(this).h;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ export class SwipeHandle {
|
||||
self.onDragHorizontal(ev);
|
||||
}
|
||||
|
||||
gesture.on('panend', gestureEv => { self.onDragEnd(gestureEv.gesture); });
|
||||
gesture.on('panend', gesture => { self.onDragEnd(gesture); });
|
||||
gesture.on('panleft', dragHorizontal);
|
||||
gesture.on('panright', dragHorizontal);
|
||||
});
|
||||
@@ -85,16 +85,14 @@ export class SwipeHandle {
|
||||
}
|
||||
|
||||
this.zone.run(() => {
|
||||
this.viewCtrl.swipeBackEnd(completeSwipeBack, progress, playbackRate);
|
||||
this.viewCtrl.swipeBackFinish(completeSwipeBack, playbackRate);
|
||||
});
|
||||
|
||||
this.startX = null;
|
||||
}
|
||||
|
||||
onDragHorizontal(gestureEv) {
|
||||
onDragHorizontal(gesture) {
|
||||
this.zone.run(() => {
|
||||
let gesture = gestureEv.gesture;
|
||||
|
||||
if (this.startX === null) {
|
||||
// starting drag
|
||||
gesture.srcEvent.preventDefault();
|
||||
|
||||
@@ -338,6 +338,8 @@ export class ViewController extends Ion {
|
||||
enteringItem.shouldCache = false;
|
||||
enteringItem.willEnter();
|
||||
|
||||
this.app.setTransitioning(true);
|
||||
|
||||
// wait for the new item to complete setup
|
||||
enteringItem.stage(() => {
|
||||
|
||||
@@ -348,8 +350,7 @@ export class ViewController extends Ion {
|
||||
|
||||
// init the transition animation
|
||||
this.sbTransition = Transition.create(this, opts);
|
||||
this.sbTransition.easing('linear');
|
||||
this.sbTransition.stage();
|
||||
this.sbTransition.easing('linear').progressStart();
|
||||
|
||||
let swipeBackPromise = new Promise(res => { this.sbResolve = res; });
|
||||
|
||||
@@ -408,27 +409,16 @@ export class ViewController extends Ion {
|
||||
* @param {TODO} progress TODO
|
||||
* @param {TODO} playbackRate TODO
|
||||
*/
|
||||
swipeBackEnd(completeSwipeBack, progress, playbackRate) {
|
||||
swipeBackFinish(completeSwipeBack, playbackRate) {
|
||||
// to reverse the animation use a negative playbackRate
|
||||
if (this.sbTransition && this.sbActive) {
|
||||
this.sbActive = false;
|
||||
|
||||
if (progress <= 0) {
|
||||
this.swipeBackProgress(0.0001);
|
||||
} else if (progress >= 1) {
|
||||
this.swipeBackProgress(0.9999);
|
||||
}
|
||||
|
||||
if (!completeSwipeBack) {
|
||||
playbackRate = playbackRate * -1;
|
||||
}
|
||||
|
||||
this.sbTransition.playbackRate(playbackRate);
|
||||
|
||||
this.sbTransition.play().then(() => {
|
||||
this.sbTransition.progressFinish(completeSwipeBack, playbackRate).then(() => {
|
||||
this.sbResolve && this.sbResolve(completeSwipeBack);
|
||||
this.sbTransition && this.sbTransition.dispose();
|
||||
this.sbResolve = this.sbTransition = null;
|
||||
this.app.setTransitioning(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user