关于这篇文章,很早前就准备写了,只是内容属于我了解的非官方资料,怕有Bug风险误导别人,又怕我表述不清楚一直没动笔,后来群里有人专门找我问这个,那我还是写一下,仅作为参考……
image.png
在了解弹窗动画前,我们先了解下CSS3中动画的基本内容:
值 | 描述 |
---|---|
transition-property | 规定设置过渡效果的 CSS 属性的名称。 |
transition-duration | 规定完成过渡效果需要多少秒或毫秒。 |
transition-timing-function | 规定速度效果的速度曲线。 |
transition-delay | 定义过渡效果何时开始。 |
其中transition-timing-function 属性规定过渡效果的速度曲线,曲线函数说明如下表所示:
值 | 描述 |
---|---|
linear | 规定以相同速度开始至结束的过渡效果(等于 cubic-bezier(0,0,1,1))。 |
ease | 规定慢速开始,然后变快,然后慢速结束的过渡效果(cubic-bezier(0.25,0.1,0.25,1))。 |
ease-in | 规定以慢速开始的过渡效果(等于 cubic-bezier(0.42,0,1,1))。 |
ease-out | 规定以慢速结束的过渡效果(等于 cubic-bezier(0,0,0.58,1))。 |
ease-in-out | 规定以慢速开始和结束的过渡效果(等于 cubic-bezier(0.42,0,0.58,1))。 |
cubic-bezier(n,n,n,n) | 在 cubic-bezier 函数中定义自己的值。可能的值是 0 至 1 之间的数值。 |
我比较了这几个效果,感觉没那么明显,建议点transition-timing-function此连接执行下里面实例感受下效果。
无事不登三宝殿,介绍到Transition,自然是因为ionic应用到它,而我这里主要说的是模态窗口modal。首先模态窗口内置了4个transitions: modal-transitions.ts,截取部分代码如下:
/** * Animations for modals */ export class ModalSlideIn extends PageTransition { init() { super.init(); const ele: HTMLElement = this.enteringView.pageRef().nativeElement; const backdropEle = ele.querySelector('ion-backdrop'); const backdrop = new Animation(this.plt, backdropEle); const wrapper = new Animation(this.plt, ele.querySelector('.modal-wrapper')); wrapper.beforeStyles({ 'opacity': 1 }); wrapper.fromTo('translateY', '100%', '0%'); backdrop.fromTo('opacity', 0.01, 0.4); this .element(this.enteringView.pageRef()) .easing('cubic-bezier(0.36,0.66,0.04,1)') .duration(400) .add(backdrop) .add(wrapper); } }
然后配置是在该源文件:modal-impl.ts,截取关键代码如下:
config.setTransition('modal-slide-in', ModalSlideIn); config.setTransition('modal-slide-out', ModalSlideOut); config.setTransition('modal-md-slide-in', ModalMDSlideIn); config.setTransition('modal-md-slide-out', ModalMDSlideOut);
从上述两份源代码可以分析得出自定义PageTransition的步骤:
1、实现一个继承PageTransition的类; 2、把该类添加到配置中。
那具体怎么实现这个类?在应用中配置和源码配置有哪些差异?配置完后怎么用呢?可以看看小军此文:ionic2实战-自定义modal过渡动画。
但是小军这篇文章有个风险的,它少了个基类的方法,我可以基本肯定他看了此链接:Ionic 2 Modal animations and custom animations?
我们应该点进去了解提供方法的作者:onderceylan,可以看到有意思的是,该作者回复了几个类似的问题:
image.png
再其中,包含上述链接在内,最有价值的链接是这个: Adding custom transitions/custom modal transition,里面有人针对风险做了回复。是的,结合源码,以及常规继承的原理,我们补充调用下基类的init方法:
super.init();
最后,基于我先前提出的几个问题,小军博客和上述链接都说明的比较清楚了,我不再说明,只是补充解析一下几个点: 1、下面部分完全是CSS3的transition内容,我们可以根据自己想要的效果来修改,其中easing里的方法个人觉得差不多,可以随便挑个用:
.element(this.enteringView.pageRef()) .easing('cubic-bezier(0.36,0.66,0.04,1)') .duration(400)
2、下面部分是CSS3的transform内容,同样可以按需修改:
wrapper.fromTo('translateY', '100%', '0%');
3、其它点,如wrapper可以调整它的透明度、宽度、高度等样式:
wrapper.beforeStyles({ 'opacity': 1 });
4、基于上述内容,提供简单示范代码如下:
import { Animation, PageTransition } from 'ionic-angular'; /** * write by IT_晴天(woodstream) */ export class ModalFromLeftEnter extends PageTransition { public init() { super.init(); const ele = this.enteringView.pageRef().nativeElement; const backdrop = new Animation(this.plt, ele.querySelector('ion-backdrop')); backdrop.beforeStyles({ 'z-index': 0, 'opacity': 0.3, 'visibility': 'visible' }); const wrapper = new Animation(this.plt, ele.querySelector('.modal-wrapper')); wrapper.fromTo('transform', 'translateX(-100%)', 'translateX(0)'); const contentWrapper = new Animation(this.plt, ele.querySelector('ion-content.content')); contentWrapper.beforeStyles({ 'width': '80%' }); this .element(this.enteringView.pageRef()) .duration(300) .easing('ease') .add(backdrop) .add(wrapper) .add(contentWrapper); } } export class ModalFromLeftLeave extends PageTransition { public init() { super.init(); const ele = this.leavingView.pageRef().nativeElement; const backdrop = new Animation(this.plt, ele.querySelector('ion-backdrop')); backdrop.beforeStyles({ 'visibility': 'hidden' }); const wrapper = new Animation(this.plt, ele.querySelector('.modal-wrapper')); wrapper.fromTo('transform', 'translateX(0)', 'translateX(-100%)'); this .element(this.leavingView.pageRef()) .duration(300) .easing('ease') .add(backdrop) .add(wrapper); } } export class ModalFromRightEnter extends PageTransition { public init() { super.init(); const ele = this.enteringView.pageRef().nativeElement; const backdrop = new Animation(this.plt, ele.querySelector('ion-backdrop')); backdrop.beforeStyles({ 'z-index': 0, 'opacity': 0.3, 'visibility': 'visible' }); const wrapper = new Animation(this.plt, ele.querySelector('.modal-wrapper')); wrapper.fromTo('transform', 'translateX(100%)', 'translateX(20%)'); const contentWrapper = new Animation(this.plt, ele.querySelector('ion-content.content')); contentWrapper.beforeStyles({ 'width': '80%' }); this .element(this.enteringView.pageRef()) .duration(300) .easing('ease') .add(backdrop) .add(wrapper) .add(contentWrapper); } } export class ModalFromRightLeave extends PageTransition { public init() { super.init(); const ele = this.leavingView.pageRef().nativeElement; const backdrop = new Animation(this.plt, ele.querySelector('ion-backdrop')); backdrop.beforeStyles({ 'visibility': 'hidden' }); const wrapper = new Animation(this.plt, ele.querySelector('.modal-wrapper')); wrapper.fromTo('transform', 'translateX(20%)', 'translateX(100%)'); this .element(this.leavingView.pageRef()) .duration(300) .easing('ease') .add(backdrop) .add(wrapper); } } export class ModalFromTopEnter extends PageTransition { public init() { super.init(); const ele = this.enteringView.pageRef().nativeElement; const backdrop = new Animation(this.plt, ele.querySelector('ion-backdrop')); backdrop.beforeStyles({ 'z-index': 0, 'opacity': 0.3, 'visibility': 'visible' }); const wrapper = new Animation(this.plt, ele.querySelector('.modal-wrapper')); wrapper.fromTo('transform', 'translateY(-100%)', 'translateY(0)'); const contentWrapper = new Animation(this.plt, ele.querySelector('ion-content.content')); contentWrapper.beforeStyles({ 'height': '60%' }); this .element(this.enteringView.pageRef()) .duration(300) .easing('ease') .add(backdrop) .add(wrapper) .add(contentWrapper); } } export class ModalFromTopLeave extends PageTransition { public init() { super.init(); const ele = this.leavingView.pageRef().nativeElement; const backdrop = new Animation(this.plt, ele.querySelector('ion-backdrop')); backdrop.beforeStyles({ 'visibility': 'hidden' }); const wrapper = new Animation(this.plt, ele.querySelector('.modal-wrapper')); wrapper.fromTo('transform', 'translateY(0)', 'translateY(-100%)'); this .element(this.leavingView.pageRef()) .duration(300) .easing('ease') .add(backdrop) .add(wrapper); } } export class ModalScaleEnter extends PageTransition { public init() { super.init(); const ele = this.enteringView.pageRef().nativeElement; const wrapper = new Animation(this.plt, ele.querySelector('.modal-wrapper')); wrapper.fromTo('transform', 'scale(0)', 'scale(1)'); this .element(this.enteringView.pageRef()) .duration(400) .easing('ease') .add(wrapper); } } export class ModalScaleLeave extends PageTransition { public init() { super.init(); const ele = this.leavingView.pageRef().nativeElement; const wrapper = new Animation(this.plt, ele.querySelector('.modal-wrapper')); wrapper.fromTo('transform', 'scale(1)', 'scale(0)'); this .element(this.leavingView.pageRef()) .duration(400) .easing('ease') .add(wrapper); } }
最后上个效果图:
animate.gif
本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。
我来说两句