| | |
| | | // 定义一个一定时间后自动成功的promise,让调用nextTick方法处,进入下一个then方法 |
| | | const waitTick = () => new Promise(resolve => setTimeout(resolve, 1000 / 50)) |
| | | // nvue动画模块实现细节抽离在外部文件 |
| | | // #ifdef APP-NVUE |
| | | import animationMap from './nvue-ani-map.js' |
| | | // #endif |
| | | |
| | | // #ifndef APP-NVUE |
| | | // 定义类名,通过给元素动态切换类名,赋予元素一定的css动画样式 |
| | | const getClassNames = (name) => ({ |
| | | enter: `u-${name}-enter u-${name}-enter-active`, |
| | | 'enter-to': `u-${name}-enter-to u-${name}-enter-active`, |
| | | leave: `u-${name}-leave u-${name}-leave-active`, |
| | | 'leave-to': `u-${name}-leave-to u-${name}-leave-active` |
| | | }) |
| | | // #endif |
| | | |
| | | // #ifdef APP-NVUE |
| | | // 引入nvue(weex)的animation动画模块,文档见: |
| | | // https://weex.apache.org/zh/docs/modules/animation.html#transition |
| | | const animation = uni.requireNativePlugin('animation') |
| | | const getStyle = (name) => animationMap[name] |
| | | // #endif |
| | | |
| | | import { nextTick } from 'vue' |
| | | import { sleep } from '../../libs/function/index'; |
| | | /* |
| | | * @Author : LQ |
| | | * @Description : |
| | | * @version : 1.0 |
| | | * @Date : 2021-08-20 16:44:21 |
| | | * @LastAuthor : LQ |
| | | * @lastTime : 2021-08-20 16:59:00 |
| | | * @FilePath : /u-view2.0/uview-ui/libs/config/props/transition.js |
| | | */ |
| | | export default { |
| | | methods: { |
| | | // 组件被点击发出事件 |
| | | clickHandler() { |
| | | this.$emit('click') |
| | | }, |
| | | // #ifndef APP-NVUE |
| | | // vue版本的组件进场处理 |
| | | async vueEnter() { |
| | | // 动画进入时的类名 |
| | | const classNames = getClassNames(this.mode) |
| | | // 定义状态和发出动画进入前事件 |
| | | this.status = 'enter' |
| | | this.$emit('beforeEnter') |
| | | this.inited = true |
| | | this.display = true |
| | | this.classes = classNames.enter |
| | | await nextTick(); |
| | | { |
| | | // https://github.com/umicro/uView2.0/issues/545 |
| | | await sleep(20) |
| | | // 标识动画尚未结束 |
| | | this.$emit('enter') |
| | | this.transitionEnded = false |
| | | // 组件动画进入后触发的事件 |
| | | this.$emit('afterEnter') |
| | | // 赋予组件enter-to类名 |
| | | this.classes = classNames['enter-to'] |
| | | } |
| | | }, |
| | | // 动画离场处理 |
| | | async vueLeave() { |
| | | // 如果不是展示状态,无需执行逻辑 |
| | | if (!this.display) return |
| | | const classNames = getClassNames(this.mode) |
| | | // 标记离开状态和发出事件 |
| | | this.status = 'leave' |
| | | this.$emit('beforeLeave') |
| | | // 获得类名 |
| | | this.classes = classNames.leave |
| | | |
| | | await nextTick(); |
| | | { |
| | | // 动画正在离场的状态 |
| | | this.transitionEnded = false |
| | | this.$emit('leave') |
| | | // 组件执行动画,到了执行的执行时间后,执行一些额外处理 |
| | | setTimeout(this.onTransitionEnd, this.duration) |
| | | this.classes = classNames['leave-to'] |
| | | } |
| | | }, |
| | | // #endif |
| | | // #ifdef APP-NVUE |
| | | // nvue版本动画进场 |
| | | async nvueEnter() { |
| | | // 获得样式的名称 |
| | | const currentStyle = getStyle(this.mode) |
| | | // 组件动画状态和发出事件 |
| | | this.status = 'enter' |
| | | this.$emit('beforeEnter') |
| | | // 展示生成组件元素 |
| | | this.inited = true |
| | | this.display = true |
| | | // 在nvue安卓上,由于渲染速度慢,在弹窗,键盘,日历等组件中,渲染其中的内容需要时间 |
| | | // 导致出现弹窗卡顿,这里让其一开始为透明状态,等一定时间渲染完成后,再让其隐藏起来,再让其按正常逻辑出现 |
| | | this.viewStyle = { |
| | | opacity: 0 |
| | | } |
| | | // 等待弹窗内容渲染完成 |
| | | await nextTick(); |
| | | { |
| | | // 合并样式 |
| | | this.viewStyle = currentStyle.enter |
| | | Promise.resolve() |
| | | .then(waitTick) |
| | | .then(() => { |
| | | // 组件开始进入前的事件 |
| | | this.$emit('enter') |
| | | // nvue的transition动画模块需要通过ref调用组件,注意此处的ref不同于vue的this.$refs['u-transition']用法 |
| | | animation.transition(this.$refs['u-transition'].ref, { |
| | | styles: currentStyle['enter-to'], |
| | | duration: this.duration, |
| | | timingFunction: this.timingFunction, |
| | | needLayout: false, |
| | | delay: 0 |
| | | }, () => { |
| | | // 动画执行完毕,发出事件 |
| | | this.$emit('afterEnter') |
| | | }) |
| | | }) |
| | | .catch(() => {}) |
| | | } |
| | | }, |
| | | nvueLeave() { |
| | | if (!this.display) { |
| | | return |
| | | } |
| | | const currentStyle = getStyle(this.mode) |
| | | // 定义状态和事件 |
| | | this.status = 'leave' |
| | | this.$emit('beforeLeave') |
| | | // 合并样式 |
| | | this.viewStyle = currentStyle.leave |
| | | // 放到promise中处理执行过程 |
| | | Promise.resolve() |
| | | .then(waitTick) // 等待几十ms |
| | | .then(() => { |
| | | this.transitionEnded = false |
| | | // 动画正在离场的状态 |
| | | this.$emit('leave') |
| | | animation.transition(this.$refs['u-transition'].ref, { |
| | | styles: currentStyle['leave-to'], |
| | | duration: this.duration, |
| | | timingFunction: this.timingFunction, |
| | | needLayout: false, |
| | | delay: 0 |
| | | }, () => { |
| | | this.onTransitionEnd() |
| | | }) |
| | | }) |
| | | .catch(() => {}) |
| | | }, |
| | | // #endif |
| | | // 完成过渡后触发 |
| | | onTransitionEnd() { |
| | | // 如果已经是结束的状态,无需再处理 |
| | | if (this.transitionEnded) return |
| | | this.transitionEnded = true |
| | | // 发出组件动画执行后的事件 |
| | | this.$emit(this.status === 'leave' ? 'afterLeave' : 'afterEnter') |
| | | if (!this.show && this.display) { |
| | | this.display = false |
| | | this.inited = false |
| | | } |
| | | } |
| | | // transition动画组件的props |
| | | transition: { |
| | | show: false, |
| | | mode: 'fade', |
| | | duration: '300', |
| | | timingFunction: 'ease-out' |
| | | } |
| | | } |