mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-19 11:41:20 +08:00
feat(menu): right side menus
This commit is contained in:
@ -35,3 +35,7 @@ ion-menu[type=overlay] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ion-menu[type=overlay][side=right] {
|
||||||
|
left: 8px;
|
||||||
|
}
|
||||||
|
@ -10,7 +10,7 @@ import {Animation} from 'ionic/animations/animation';
|
|||||||
*/
|
*/
|
||||||
export class MenuType {
|
export class MenuType {
|
||||||
|
|
||||||
constructor(menu: Menu) {
|
constructor() {
|
||||||
this.open = new Animation();
|
this.open = new Animation();
|
||||||
this.close = new Animation();
|
this.close = new Animation();
|
||||||
}
|
}
|
||||||
@ -88,16 +88,17 @@ class MenuRevealType extends MenuType {
|
|||||||
let duration = 250;
|
let duration = 250;
|
||||||
|
|
||||||
let openedX = (menu.width() * (menu.side == 'right' ? -1 : 1)) + 'px';
|
let openedX = (menu.width() * (menu.side == 'right' ? -1 : 1)) + 'px';
|
||||||
|
let closedX = '0px'
|
||||||
|
|
||||||
this.open.easing(easing).duration(duration);
|
this.open.easing(easing).duration(duration);
|
||||||
this.close.easing(easing).duration(duration);
|
this.close.easing(easing).duration(duration);
|
||||||
|
|
||||||
let contentOpen = new Animation(menu.getContentElement());
|
let contentOpen = new Animation(menu.getContentElement());
|
||||||
contentOpen.fromTo(TRANSLATE_X, CENTER, openedX);
|
contentOpen.fromTo(TRANSLATE_X, closedX, openedX);
|
||||||
this.open.add(contentOpen);
|
this.open.add(contentOpen);
|
||||||
|
|
||||||
let contentClose = new Animation(menu.getContentElement());
|
let contentClose = new Animation(menu.getContentElement());
|
||||||
contentClose.fromTo(TRANSLATE_X, openedX, CENTER);
|
contentClose.fromTo(TRANSLATE_X, openedX, closedX);
|
||||||
this.close.add(contentClose);
|
this.close.add(contentClose);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,13 +118,23 @@ class MenuOverlayType extends MenuType {
|
|||||||
let duration = 250;
|
let duration = 250;
|
||||||
let backdropOpacity = 0.5;
|
let backdropOpacity = 0.5;
|
||||||
|
|
||||||
let closedX = (menu.width() * (menu.side == 'right' ? 1 : -1)) + 'px';
|
let closedX, openedX;
|
||||||
|
if (menu.side == 'right') {
|
||||||
|
// right side
|
||||||
|
closedX = menu.platform.width() + 'px';
|
||||||
|
openedX = (menu.platform.width() - menu.width() - 8) + 'px';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// left side
|
||||||
|
closedX = -menu.width() + 'px';
|
||||||
|
openedX = '8px';
|
||||||
|
}
|
||||||
|
|
||||||
this.open.easing(easing).duration(duration);
|
this.open.easing(easing).duration(duration);
|
||||||
this.close.easing(easing).duration(duration);
|
this.close.easing(easing).duration(duration);
|
||||||
|
|
||||||
let menuOpen = new Animation(menu.getMenuElement());
|
let menuOpen = new Animation(menu.getMenuElement());
|
||||||
menuOpen.fromTo(TRANSLATE_X, closedX, '8px');
|
menuOpen.fromTo(TRANSLATE_X, closedX, openedX);
|
||||||
this.open.add(menuOpen);
|
this.open.add(menuOpen);
|
||||||
|
|
||||||
let backdropOpen = new Animation(menu.getBackdropElement());
|
let backdropOpen = new Animation(menu.getBackdropElement());
|
||||||
@ -131,7 +142,7 @@ class MenuOverlayType extends MenuType {
|
|||||||
this.open.add(backdropOpen);
|
this.open.add(backdropOpen);
|
||||||
|
|
||||||
let menuClose = new Animation(menu.getMenuElement());
|
let menuClose = new Animation(menu.getMenuElement());
|
||||||
menuClose.fromTo(TRANSLATE_X, '8px', closedX);
|
menuClose.fromTo(TRANSLATE_X, openedX, closedX);
|
||||||
this.close.add(menuClose);
|
this.close.add(menuClose);
|
||||||
|
|
||||||
let backdropClose = new Animation(menu.getBackdropElement());
|
let backdropClose = new Animation(menu.getBackdropElement());
|
||||||
@ -144,4 +155,3 @@ Menu.register('overlay', MenuOverlayType);
|
|||||||
|
|
||||||
const OPACITY = 'opacity';
|
const OPACITY = 'opacity';
|
||||||
const TRANSLATE_X = 'translateX';
|
const TRANSLATE_X = 'translateX';
|
||||||
const CENTER = '0px';
|
|
||||||
|
@ -4,6 +4,7 @@ import {Ion} from '../ion';
|
|||||||
import {IonicApp} from '../app/app';
|
import {IonicApp} from '../app/app';
|
||||||
import {IonicConfig} from '../../config/config';
|
import {IonicConfig} from '../../config/config';
|
||||||
import {IonicComponent} from '../../config/annotations';
|
import {IonicComponent} from '../../config/annotations';
|
||||||
|
import {IonicPlatform} from '../../platform/platform';
|
||||||
import * as gestures from './menu-gestures';
|
import * as gestures from './menu-gestures';
|
||||||
|
|
||||||
|
|
||||||
@ -35,10 +36,16 @@ import * as gestures from './menu-gestures';
|
|||||||
})
|
})
|
||||||
export class Menu extends Ion {
|
export class Menu extends Ion {
|
||||||
|
|
||||||
constructor(app: IonicApp, elementRef: ElementRef, config: IonicConfig) {
|
constructor(
|
||||||
|
app: IonicApp,
|
||||||
|
elementRef: ElementRef,
|
||||||
|
config: IonicConfig,
|
||||||
|
platform: IonicPlatform
|
||||||
|
) {
|
||||||
super(elementRef, config);
|
super(elementRef, config);
|
||||||
|
|
||||||
this.app = app;
|
this.app = app;
|
||||||
|
this.platform = platform;
|
||||||
|
|
||||||
this.opening = new EventEmitter('opening');
|
this.opening = new EventEmitter('opening');
|
||||||
this.isOpen = false;
|
this.isOpen = false;
|
||||||
this._disableTime = 0;
|
this._disableTime = 0;
|
||||||
@ -46,9 +53,9 @@ export class Menu extends Ion {
|
|||||||
|
|
||||||
onInit() {
|
onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
this.contentElement = (this.content instanceof Node) ? this.content : this.content.getNativeElement();
|
this._cntEle = (this.content instanceof Node) ? this.content : this.content.getNativeElement();
|
||||||
|
|
||||||
if (!this.contentElement) {
|
if (!this._cntEle) {
|
||||||
return console.error('Menu: must have a [content] element to listen for drag events on. Example:\n\n<ion-menu [content]="content"></ion-menu>\n\n<ion-content #content></ion-content>');
|
return console.error('Menu: must have a [content] element to listen for drag events on. Example:\n\n<ion-menu [content]="content"></ion-menu>\n\n<ion-content #content></ion-content>');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,8 +68,8 @@ export class Menu extends Ion {
|
|||||||
this._initGesture();
|
this._initGesture();
|
||||||
this._initType(this.type);
|
this._initType(this.type);
|
||||||
|
|
||||||
this.contentElement.classList.add('menu-content');
|
this._cntEle.classList.add('menu-content');
|
||||||
this.contentElement.classList.add('menu-content-' + this.type);
|
this._cntEle.classList.add('menu-content-' + this.type);
|
||||||
|
|
||||||
let self = this;
|
let self = this;
|
||||||
this.onContentClick = function(ev) {
|
this.onContentClick = function(ev) {
|
||||||
@ -161,11 +168,11 @@ export class Menu extends Ion {
|
|||||||
|
|
||||||
this.isOpen = isOpen;
|
this.isOpen = isOpen;
|
||||||
|
|
||||||
this.contentElement.classList[isOpen ? 'add' : 'remove']('menu-content-open');
|
this._cntEle.classList[isOpen ? 'add' : 'remove']('menu-content-open');
|
||||||
|
|
||||||
this.contentElement.removeEventListener('click', this.onContentClick);
|
this._cntEle.removeEventListener('click', this.onContentClick);
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
this.contentElement.addEventListener('click', this.onContentClick);
|
this._cntEle.addEventListener('click', this.onContentClick);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.getNativeElement().classList.remove('show-menu');
|
this.getNativeElement().classList.remove('show-menu');
|
||||||
@ -220,7 +227,7 @@ export class Menu extends Ion {
|
|||||||
* @return {Element} The Menu's associated content element.
|
* @return {Element} The Menu's associated content element.
|
||||||
*/
|
*/
|
||||||
getContentElement() {
|
getContentElement() {
|
||||||
return this.contentElement;
|
return this._cntEle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -239,7 +246,7 @@ export class Menu extends Ion {
|
|||||||
this.app.unregister(this.id);
|
this.app.unregister(this.id);
|
||||||
this._gesture && this._gesture.destroy();
|
this._gesture && this._gesture.destroy();
|
||||||
this._type && this._type.onDestroy();
|
this._type && this._type.onDestroy();
|
||||||
this.contentElement = null;
|
this._cntEle = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,9 +36,9 @@ class E2EApp {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
openPage(menu, page) {
|
openPage(page) {
|
||||||
// close the menu when clicking a link from the menu
|
// close the menu when clicking a link from the menu
|
||||||
menu.close();
|
this.app.getComponent('leftMenu').close();
|
||||||
|
|
||||||
// Reset the content nav to have just this page
|
// Reset the content nav to have just this page
|
||||||
// we wouldn't want the back button to show in this scenario
|
// we wouldn't want the back button to show in this scenario
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<ion-menu #menu [content]="content">
|
<ion-menu [content]="content" id="leftMenu">
|
||||||
|
|
||||||
<ion-toolbar secondary>
|
<ion-toolbar secondary>
|
||||||
<ion-title>Left Menu</ion-title>
|
<ion-title>Left Menu</ion-title>
|
||||||
@ -8,11 +8,35 @@
|
|||||||
|
|
||||||
<ion-list>
|
<ion-list>
|
||||||
|
|
||||||
<button ion-item *ng-for="#p of pages" (click)="openPage(menu, p)">
|
<button ion-item *ng-for="#p of pages" (click)="openPage(p)">
|
||||||
{{p.title}}
|
{{p.title}}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button ion-item menu-toggle no-forward-icon class="e2eCloseMenu">
|
<button ion-item menu-toggle="leftMenu" no-forward-icon class="e2eCloseMenu">
|
||||||
|
Close Menu
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</ion-list>
|
||||||
|
</ion-content>
|
||||||
|
|
||||||
|
</ion-menu>
|
||||||
|
|
||||||
|
|
||||||
|
<ion-menu side="right" [content]="content" id="rightMenu">
|
||||||
|
|
||||||
|
<ion-toolbar secondary>
|
||||||
|
<ion-title>Right Menu</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
|
||||||
|
<ion-content>
|
||||||
|
|
||||||
|
<ion-list>
|
||||||
|
|
||||||
|
<button ion-item *ng-for="#p of pages" (click)="openPage(p)">
|
||||||
|
{{p.title}}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button ion-item menu-toggle="rightMenu" no-forward-icon class="e2eCloseMenu">
|
||||||
Close Menu
|
Close Menu
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
<ion-navbar *navbar>
|
<ion-navbar *navbar>
|
||||||
|
|
||||||
<a menu-toggle>
|
<a menu-toggle="leftMenu">
|
||||||
<icon menu></icon>
|
<icon menu></icon>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -21,19 +21,23 @@
|
|||||||
</button>
|
</button>
|
||||||
</ion-nav-items>
|
</ion-nav-items>
|
||||||
|
|
||||||
<a menu-toggle secondary>
|
<a menu-toggle="rightMenu" secondary>
|
||||||
<icon menu></icon>
|
<icon menu></icon>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
</ion-navbar>
|
</ion-navbar>
|
||||||
|
|
||||||
|
|
||||||
<ion-content #content padding>
|
<ion-content padding>
|
||||||
|
|
||||||
<h3>Page 1</h3>
|
<h3>Page 1</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<button class="e2eContentToggleMenu" menu-toggle>Toggle Menu</button>
|
<button class="e2eContentToggleMenu" menu-toggle="leftMenu">Toggle Left Menu</button>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<button class="e2eContentToggleMenu" menu-toggle="rightMenu">Toggle Right Menu</button>
|
||||||
</p>
|
</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>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
<ion-navbar *navbar>
|
<ion-navbar *navbar>
|
||||||
|
|
||||||
<a menu-toggle>
|
<a menu-toggle="leftMenu">
|
||||||
<icon menu></icon>
|
<icon menu></icon>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -11,12 +11,12 @@
|
|||||||
|
|
||||||
</ion-navbar>
|
</ion-navbar>
|
||||||
|
|
||||||
<ion-content #content padding>
|
<ion-content padding>
|
||||||
|
|
||||||
<h3>Page 2</h3>
|
<h3>Page 2</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<button menu-toggle class="e2eContentToggleMenu">Toggle Menu</button>
|
<button menu-toggle="leftMenu" class="e2eContentToggleMenu">Toggle Left Menu</button>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
<ion-navbar *navbar>
|
<ion-navbar *navbar>
|
||||||
|
|
||||||
<a menu-toggle>
|
<a menu-toggle="leftMenu">
|
||||||
<icon menu></icon>
|
<icon menu></icon>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -12,12 +12,12 @@
|
|||||||
</ion-navbar>
|
</ion-navbar>
|
||||||
|
|
||||||
|
|
||||||
<ion-content #content padding>
|
<ion-content padding>
|
||||||
|
|
||||||
<h3>Page 3</h3>
|
<h3>Page 3</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<button menu-toggle>Toggle Menu</button>
|
<button menu-toggle="leftMenu">Toggle Left Menu</button>
|
||||||
</p>
|
</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>
|
||||||
|
@ -43,6 +43,12 @@ $toolbar-md-button-font-size: 1.4rem !default;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[menu-toggle][secondary],
|
||||||
|
[menu-toggle][secondary].activated {
|
||||||
|
margin: 0 2px;
|
||||||
|
min-width: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-title {
|
ion-title {
|
||||||
|
Reference in New Issue
Block a user