如何自定义侧面菜单动画

时间:2019-08-04 01:04:19

标签: ionic-framework ionic4

我正在开发Ionic 4应用程序,我想使用这样的自定义侧面菜单动画:

enter image description here

但是Ionic只有3个选项:推入,覆盖和显示。

我已经有了我的3dmenu.ts文件,但我没有像其他3个选项一样将其与离子菜单组件一起注入使用的方法,有人可以提供有关如何执行此操作的提示吗?

1 个答案:

答案 0 :(得分:0)

我终于可以做到了,比我在这里here使用了workaruond。诀窍是扩展菜单控制器类以创建新方法registerAnimation:

第1步:创建一个新的ts文件(extended.ts或您想要的名称),然后将此代码放入其中:

import { DOCUMENT } from '@angular/common';
import { Inject, Injectable } from '@angular/core';

import { MenuController } from '@ionic/angular';
import { AnimationBuilder } from '@ionic/core';

function proxyMethod(ctrlName: string, doc: Document, methodName: string, ...args: any[]) {
    const controller = ensureElementInBody(ctrlName, doc);
    return controller.componentOnReady()
        .then(() => (controller as any)[methodName].apply(controller, args));
}

function ensureElementInBody(elementName: string, doc: Document) {
    let element = doc.querySelector(elementName);
    if (!element) {
        element = doc.createElement(elementName);
        doc.body.appendChild(element);
    }
    return element as HTMLStencilElement;
}

const CTRL = 'ion-menu-controller';
@Injectable({
    providedIn: 'root',
})

export class EloMenuController extends MenuController {

    constructor(@Inject(DOCUMENT) private document: any) {
        super(document)
    }

    /**
    * Registers a new animation that can be used with any `ion-menu` by
    * passing the name of the animation in its `type` property.
    *
    * @param name The name of the animation to register.
    * @param animation The animation function to register.
    */
    registerAnimation(name: string, animation: AnimationBuilder) {
        return proxyMethod(CTRL, this.document, 'registerAnimation', name, animation);
    }
}

第2步:使用动画创建一个新的ts文件,在我的情况下,我使用以下文件:

import { Animation, MenuI } from '@ionic/core';

export function menu3D (AnimationC: Animation, baseEl: HTMLElement, menu: MenuI):     
Promise<Animation> {        

    let contentOpenedX: string;
    let menuClosedX: string;
    const width = menu.width;
    const baseAnimation = new AnimationC();

    if (menu.isEndSide) {
        contentOpenedX = -width + 'px';
        menuClosedX = width + 'px';
    } 
    else {
        contentOpenedX = width + 'px';
        menuClosedX = -width + 'px';
    }

    const menuAnimation = new AnimationC()
        .addElement(menu.menuInnerEl)
        .fromTo('z-index', '0', '0')
        .fromTo('translateX', menuClosedX, '0px');

   const contentAnimation = new AnimationC()
       .addElement(menu.contentEl)
       .fromTo('translateX', '0px', contentOpenedX)
       .fromTo('scale', '1', '0.7');

   const backdropAnimation = new AnimationC()
       .addElement(menu.backdropEl)
       .fromTo('opacity', 0.01, 0.32);

   return Promise.resolve(baseAnimation
       .addElement(baseEl)
       .easing('cubic-bezier(0.0, 0.0, 0.2, 1)')
       .easingReverse('cubic-bezier(0.4, 0.0, 0.6, 1)')
       .duration(300)
       .add(contentAnimation)
       .add(menuAnimation)
       .add(backdropAnimation));
};

第3步:将扩展类和动画导入到app.component.ts中,并注册动画以使用它:

import { Component, OnInit, Input } from '@angular/core';
import { Extend } from './animations/extend
import { menu3D } from './animations/menu3D';

@Component({
    selector: 'app-root',
    templateUrl: 'app.component.html',
})

export class AppComponent implements OnInit {

    @Input() name: string;

    constructor(
        private menu: Extend
    ) {
        this.menu.registerAnimation('menu3d', menu3D);
    }

    ngOnInit() {}
}

第4步:配置离子菜单组件的类型

<ion-menu side="start" type="menu3d" style="z-index: 10;">
    ........
</ion-menu>

第5步:别忘了感谢github上的svallory并享受它:-)

我不知道这是否是最好的方法,但是它是我经过5天的搜索后发现的唯一方法,我希望这对其他人有帮助,如果有人可以改善此方法,请随时发表评论:-)