¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view> |
| | | </template> |
| | | |
| | | <script> |
| | | import { createAnimation } from './createAnimation' |
| | | |
| | | /** |
| | | * Transition è¿æ¸¡å¨ç» |
| | | * @description ç®åè¿æ¸¡å¨ç»ç»ä»¶ |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=985 |
| | | * @property {Boolean} show = [false|true] æ§å¶ç»ä»¶æ¾ç¤ºæéè |
| | | * @property {Array|String} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] è¿æ¸¡å¨ç»ç±»å |
| | | * @value fade æ¸éæ¸åºè¿æ¸¡ |
| | | * @value slide-top ç±ä¸è³ä¸è¿æ¸¡ |
| | | * @value slide-right ç±å³è³å·¦è¿æ¸¡ |
| | | * @value slide-bottom ç±ä¸è³ä¸è¿æ¸¡ |
| | | * @value slide-left ç±å·¦è³å³è¿æ¸¡ |
| | | * @value zoom-in ç±å°å°å¤§è¿æ¸¡ |
| | | * @value zoom-out ç±å¤§å°å°è¿æ¸¡ |
| | | * @property {Number} duration è¿æ¸¡å¨ç»æç»æ¶é´ |
| | | * @property {Object} styles ç»ä»¶æ ·å¼ï¼å css æ ·å¼ï¼æ³¨æå¸¦â-âè¿æ¥ç¬¦ç屿§éè¦ä½¿ç¨å°é©¼å³°åæ³å¦ï¼`backgroundColor:red` |
| | | */ |
| | | export default { |
| | | name: 'uniTransition', |
| | | emits:['click','change'], |
| | | props: { |
| | | show: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | modeClass: { |
| | | type: [Array, String], |
| | | default() { |
| | | return 'fade' |
| | | } |
| | | }, |
| | | duration: { |
| | | type: Number, |
| | | default: 300 |
| | | }, |
| | | styles: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | }, |
| | | customClass:{ |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | isShow: false, |
| | | transform: '', |
| | | opacity: 1, |
| | | animationData: {}, |
| | | durationTime: 300, |
| | | config: {} |
| | | } |
| | | }, |
| | | watch: { |
| | | show: { |
| | | handler(newVal) { |
| | | if (newVal) { |
| | | this.open() |
| | | } else { |
| | | // é¿å
䏿¥å°±æ§è¡ close,导è´å¨ç»éä¹± |
| | | if (this.isShow) { |
| | | this.close() |
| | | } |
| | | } |
| | | }, |
| | | immediate: true |
| | | } |
| | | }, |
| | | computed: { |
| | | // çææ ·å¼æ°æ® |
| | | stylesObject() { |
| | | let styles = { |
| | | ...this.styles, |
| | | 'transition-duration': this.duration / 1000 + 's' |
| | | } |
| | | let transform = '' |
| | | for (let i in styles) { |
| | | let line = this.toLine(i) |
| | | transform += line + ':' + styles[i] + ';' |
| | | } |
| | | return transform |
| | | }, |
| | | // åå§åå¨ç»æ¡ä»¶ |
| | | transformStyles() { |
| | | return 'transform:' + this.transform + ';' + 'opacity:' + this.opacity + ';' + this.stylesObject |
| | | } |
| | | }, |
| | | created() { |
| | | // å¨ç»é»è®¤é
ç½® |
| | | this.config = { |
| | | duration: this.duration, |
| | | timingFunction: 'ease', |
| | | transformOrigin: '50% 50%', |
| | | delay: 0 |
| | | } |
| | | this.durationTime = this.duration |
| | | }, |
| | | methods: { |
| | | /** |
| | | * ref 触å åå§åå¨ç» |
| | | */ |
| | | init(obj = {}) { |
| | | if (obj.duration) { |
| | | this.durationTime = obj.duration |
| | | } |
| | | this.animation = createAnimation(Object.assign(this.config, obj),this) |
| | | }, |
| | | /** |
| | | * ç¹å»ç»ä»¶è§¦ååè° |
| | | */ |
| | | onClick() { |
| | | this.$emit('click', { |
| | | detail: this.isShow |
| | | }) |
| | | }, |
| | | /** |
| | | * ref 触å å¨ç»åç» |
| | | * @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]) |
| | | } |
| | | } catch (e) { |
| | | console.error(`æ¹æ³ ${i} ä¸åå¨`) |
| | | } |
| | | } |
| | | this.animation.step(config) |
| | | return this |
| | | }, |
| | | /** |
| | | * ref è§¦å æ§è¡å¨ç» |
| | | */ |
| | | run(fn) { |
| | | if (!this.animation) return |
| | | this.animation.run(fn) |
| | | }, |
| | | // å¼å§è¿åº¦å¨ç» |
| | | 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 |
| | | // ç¡®ä¿å¨ææ ·å¼å·²ç»çæåï¼æ§è¡å¨ç»ï¼å¦æä¸å nextTick ï¼ä¼å¯¼è´ wx å¨ç»æ§è¡å¼å¸¸ |
| | | this.$nextTick(() => { |
| | | // TODO 宿¶å¨ä¿è¯å¨ç»å®å
¨æ§è¡ï¼ç®åæäºé®é¢ï¼åé¢ä¼åæ¶å®æ¶å¨ |
| | | this.timer = setTimeout(() => { |
| | | this.animation = createAnimation(this.config, this) |
| | | this.tranfromInit(false).step() |
| | | this.animation.run() |
| | | this.$emit('change', { |
| | | detail: this.isShow |
| | | }) |
| | | }, 20) |
| | | }) |
| | | }, |
| | | // å
³éè¿åº¦å¨ç» |
| | | close(type) { |
| | | if (!this.animation) return |
| | | this.tranfromInit(true) |
| | | .step() |
| | | .run(() => { |
| | | this.isShow = false |
| | | this.animationData = null |
| | | this.animation = null |
| | | let { opacity, transform } = this.styleInit(false) |
| | | this.opacity = opacity || 1 |
| | | this.transform = transform |
| | | this.$emit('change', { |
| | | detail: this.isShow |
| | | }) |
| | | }) |
| | | }, |
| | | // å¤çå¨ç»å¼å§åçé»è®¤æ ·å¼ |
| | | styleInit(type) { |
| | | let styles = { |
| | | transform: '' |
| | | } |
| | | let buildStyle = (type, mode) => { |
| | | if (mode === 'fade') { |
| | | styles.opacity = this.animationType(type)[mode] |
| | | } else { |
| | | styles.transform += this.animationType(type)[mode] + ' ' |
| | | } |
| | | } |
| | | if (typeof this.modeClass === 'string') { |
| | | buildStyle(type, this.modeClass) |
| | | } else { |
| | | this.modeClass.forEach(mode => { |
| | | buildStyle(type, mode) |
| | | }) |
| | | } |
| | | return styles |
| | | }, |
| | | // å¤çå
ç½®ç»åå¨ç» |
| | | tranfromInit(type) { |
| | | let buildTranfrom = (type, mode) => { |
| | | let aniNum = null |
| | | if (mode === 'fade') { |
| | | aniNum = type ? 0 : 1 |
| | | } else { |
| | | aniNum = type ? '-100%' : '0' |
| | | if (mode === 'zoom-in') { |
| | | aniNum = type ? 0.8 : 1 |
| | | } |
| | | if (mode === 'zoom-out') { |
| | | aniNum = type ? 1.2 : 1 |
| | | } |
| | | if (mode === 'slide-right') { |
| | | aniNum = type ? '100%' : '0' |
| | | } |
| | | if (mode === 'slide-bottom') { |
| | | aniNum = type ? '100%' : '0' |
| | | } |
| | | } |
| | | this.animation[this.animationMode()[mode]](aniNum) |
| | | } |
| | | if (typeof this.modeClass === 'string') { |
| | | buildTranfrom(type, this.modeClass) |
| | | } else { |
| | | this.modeClass.forEach(mode => { |
| | | buildTranfrom(type, mode) |
| | | }) |
| | | } |
| | | |
| | | return this.animation |
| | | }, |
| | | animationType(type) { |
| | | return { |
| | | fade: type ? 1 : 0, |
| | | 'slide-top': `translateY(${type ? '0' : '-100%'})`, |
| | | 'slide-right': `translateX(${type ? '0' : '100%'})`, |
| | | 'slide-bottom': `translateY(${type ? '0' : '100%'})`, |
| | | 'slide-left': `translateX(${type ? '0' : '-100%'})`, |
| | | 'zoom-in': `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`, |
| | | 'zoom-out': `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})` |
| | | } |
| | | }, |
| | | // å
ç½®å¨ç»ç±»åä¸å®é
å¨ç»å¯¹åºåå
¸ |
| | | animationMode() { |
| | | return { |
| | | fade: 'opacity', |
| | | 'slide-top': 'translateY', |
| | | 'slide-right': 'translateX', |
| | | 'slide-bottom': 'translateY', |
| | | 'slide-left': 'translateX', |
| | | 'zoom-in': 'scale', |
| | | 'zoom-out': 'scale' |
| | | } |
| | | }, |
| | | // é©¼å³°è½¬ä¸æ¨ªçº¿ |
| | | toLine(name) { |
| | | return name.replace(/([A-Z])/g, '-$1').toLowerCase() |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style></style> |