| | |
| | | <template> |
| | | <!-- #ifndef APP-NVUE --> |
| | | <view v-show="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view> |
| | | <view v-show="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"> |
| | | <slot></slot> |
| | | </view> |
| | | <!-- #endif --> |
| | | <!-- #ifdef APP-NVUE --> |
| | | <view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view> |
| | | <view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"> |
| | | <slot></slot> |
| | | </view> |
| | | <!-- #endif --> |
| | | </template> |
| | | |
| | |
| | | return { |
| | | isShow: false, |
| | | transform: '', |
| | | opacity: 1, |
| | | opacity: 0, |
| | | animationData: {}, |
| | | durationTime: 300, |
| | | config: {} |
| | |
| | | * @param {Object} obj |
| | | */ |
| | | step(obj, config = {}) { |
| | | if (!this.animation) return |
| | | for (let i in obj) { |
| | | try { |
| | | if(typeof obj[i] === 'object'){ |
| | | this.animation[i](...obj[i]) |
| | | }else{ |
| | | this.animation[i](obj[i]) |
| | | if (!this.animation) return this |
| | | Object.keys(obj).forEach(key => { |
| | | const value = obj[key] |
| | | if (typeof this.animation[key] === 'function') { |
| | | Array.isArray(value) ? |
| | | this.animation[key](...value) : |
| | | this.animation[key](value) |
| | | } |
| | | } catch (e) { |
| | | console.error(`方法 ${i} 不存在`) |
| | | } |
| | | } |
| | | }) |
| | | this.animation.step(config) |
| | | return this |
| | | }, |
| | |
| | | // 开始过度动画 |
| | | open() { |
| | | clearTimeout(this.timer) |
| | | this.transform = '' |
| | | this.isShow = true |
| | | let { opacity, transform } = this.styleInit(false) |
| | | if (typeof opacity !== 'undefined') { |
| | | this.opacity = opacity |
| | | } |
| | | this.transform = transform |
| | | // 新增初始状态重置逻辑(关键) |
| | | this.transform = this.styleInit(false).transform || '' |
| | | this.opacity = this.styleInit(false).opacity || 0 |
| | | |
| | | // 确保动态样式已经生效后,执行动画,如果不加 nextTick ,会导致 wx 动画执行异常 |
| | | this.$nextTick(() => { |
| | | // TODO 定时器保证动画完全执行,目前有些问题,后面会取消定时器 |
| | |
| | | this.tranfromInit(false).step() |
| | | this.animation.run(() => { |
| | | this.transform = '' |
| | | this.opacity = opacity || 1 |
| | | }) |
| | | this.opacity = this.styleInit(false).opacity || 1 |
| | | this.$emit('change', { |
| | | detail: this.isShow |
| | | }) |
| | | }, 20) |
| | | }) |
| | | }, 80) |
| | | }) |
| | | }, |
| | | // 关闭过度动画 |
| | |
| | | }, |
| | | // 处理动画开始前的默认样式 |
| | | styleInit(type) { |
| | | let styles = { |
| | | transform: '' |
| | | } |
| | | let buildStyle = (type, mode) => { |
| | | if (mode === 'fade') { |
| | | styles.opacity = this.animationType(type)[mode] |
| | | let styles = { transform: '', opacity: 1 } |
| | | const buildStyle = (type, mode) => { |
| | | const value = this.animationType(type)[mode] // 直接使用 type 控制状态 |
| | | if (mode.startsWith('fade')) { |
| | | styles.opacity = value |
| | | } else { |
| | | styles.transform += this.animationType(type)[mode] + ' ' |
| | | styles.transform += value + ' ' |
| | | } |
| | | } |
| | | |
| | | if (typeof this.modeClass === 'string') { |
| | | buildStyle(type, this.modeClass) |
| | | } else { |
| | | this.modeClass.forEach(mode => { |
| | | buildStyle(type, mode) |
| | | }) |
| | | this.modeClass.forEach(mode => buildStyle(type, mode)) |
| | | } |
| | | return styles |
| | | }, |
| | |
| | | }, |
| | | animationType(type) { |
| | | return { |
| | | fade: type ? 0 : 1, |
| | | fade: type ? 1 : 0, |
| | | 'slide-top': `translateY(${type ? '0' : '-100%'})`, |
| | | 'slide-right': `translateX(${type ? '0' : '100%'})`, |
| | | 'slide-bottom': `translateY(${type ? '0' : '100%'})`, |