From b1ad3da0513c1e3e9d0e4ed294cd7a68aa65102f Mon Sep 17 00:00:00 2001 From: li-guang <153605324@qq.com> Date: Wed, 06 Jan 2021 19:15:35 +0800 Subject: [PATCH] 跟进记录 --- hive-app/components/uni-transition/uni-transition.vue | 279 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 279 insertions(+), 0 deletions(-) diff --git a/hive-app/components/uni-transition/uni-transition.vue b/hive-app/components/uni-transition/uni-transition.vue new file mode 100644 index 0000000..908a939 --- /dev/null +++ b/hive-app/components/uni-transition/uni-transition.vue @@ -0,0 +1,279 @@ +<template> + <view v-if="isShow" ref="ani" class="uni-transition" :class="[ani.in]" :style="'transform:' +transform+';'+stylesObject" + @click="change"> + <slot></slot> + </view> +</template> + +<script> + // #ifdef APP-NVUE + const animation = uni.requireNativePlugin('animation'); + // #endif + /** + * Transition 过渡动画 + * @description 简单过渡动画组件 + * @tutorial https://ext.dcloud.net.cn/plugin?id=985 + * @property {Boolean} show = [false|true] 控制组件显示或隐藏 + * @property {Array} 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', + props: { + show: { + type: Boolean, + default: false + }, + modeClass: { + type: Array, + default () { + return [] + } + }, + duration: { + type: Number, + default: 300 + }, + styles: { + type: Object, + default () { + return {} + } + } + }, + data() { + return { + isShow: false, + transform: '', + ani: { in: '', + active: '' + } + }; + }, + watch: { + show: { + handler(newVal) { + if (newVal) { + this.open() + } else { + this.close() + } + }, + immediate: true + } + }, + computed: { + stylesObject() { + let styles = { + ...this.styles, + 'transition-duration': this.duration / 1000 + 's' + } + let transfrom = '' + for (let i in styles) { + let line = this.toLine(i) + transfrom += line + ':' + styles[i] + ';' + } + return transfrom + } + }, + created() { + // this.timer = null + // this.nextTick = (time = 50) => new Promise(resolve => { + // clearTimeout(this.timer) + // this.timer = setTimeout(resolve, time) + // return this.timer + // }); + }, + methods: { + change() { + this.$emit('click', { + detail: this.isShow + }) + }, + open() { + clearTimeout(this.timer) + this.isShow = true + this.transform = '' + this.ani.in = '' + for (let i in this.getTranfrom(false)) { + if (i === 'opacity') { + this.ani.in = 'fade-in' + } else { + this.transform += `${this.getTranfrom(false)[i]} ` + } + } + this.$nextTick(() => { + setTimeout(() => { + this._animation(true) + }, 50) + }) + + }, + close(type) { + clearTimeout(this.timer) + this._animation(false) + }, + _animation(type) { + let styles = this.getTranfrom(type) + // #ifdef APP-NVUE + if(!this.$refs['ani']) return + animation.transition(this.$refs['ani'].ref, { + styles, + duration: this.duration, //ms + timingFunction: 'ease', + needLayout: false, + delay: 0 //ms + }, () => { + if (!type) { + this.isShow = false + } + this.$emit('change', { + detail: this.isShow + }) + }) + // #endif + // #ifndef APP-NVUE + this.transform = '' + for (let i in styles) { + if (i === 'opacity') { + this.ani.in = `fade-${type?'out':'in'}` + } else { + this.transform += `${styles[i]} ` + } + } + this.timer = setTimeout(() => { + if (!type) { + this.isShow = false + } + this.$emit('change', { + detail: this.isShow + }) + + }, this.duration) + // #endif + + }, + getTranfrom(type) { + let styles = { + transform: '' + } + this.modeClass.forEach((mode) => { + switch (mode) { + case 'fade': + styles.opacity = type ? 1 : 0 + break; + case 'slide-top': + styles.transform += `translateY(${type?'0':'-100%'}) ` + break; + case 'slide-right': + styles.transform += `translateX(${type?'0':'100%'}) ` + break; + case 'slide-bottom': + styles.transform += `translateY(${type?'0':'100%'}) ` + break; + case 'slide-left': + styles.transform += `translateX(${type?'0':'-100%'}) ` + break; + case 'zoom-in': + styles.transform += `scale(${type?1:0.8}) ` + break; + case 'zoom-out': + styles.transform += `scale(${type?1:1.2}) ` + break; + } + }) + return styles + }, + _modeClassArr(type) { + let mode = this.modeClass + if (typeof(mode) !== "string") { + let modestr = '' + mode.forEach((item) => { + modestr += (item + '-' + type + ',') + }) + return modestr.substr(0, modestr.length - 1) + } else { + return mode + '-' + type + } + }, + // getEl(el) { + // console.log(el || el.ref || null); + // return el || el.ref || null + // }, + toLine(name) { + return name.replace(/([A-Z])/g, "-$1").toLowerCase(); + } + } + } +</script> + +<style> + .uni-transition { + transition-timing-function: ease; + transition-duration: 0.3s; + transition-property: transform, opacity; + } + + .fade-in { + opacity: 0; + } + + .fade-active { + opacity: 1; + } + + .slide-top-in { + /* transition-property: transform, opacity; */ + transform: translateY(-100%); + } + + .slide-top-active { + transform: translateY(0); + /* opacity: 1; */ + } + + .slide-right-in { + transform: translateX(100%); + } + + .slide-right-active { + transform: translateX(0); + } + + .slide-bottom-in { + transform: translateY(100%); + } + + .slide-bottom-active { + transform: translateY(0); + } + + .slide-left-in { + transform: translateX(-100%); + } + + .slide-left-active { + transform: translateX(0); + opacity: 1; + } + + .zoom-in-in { + transform: scale(0.8); + } + + .zoom-out-active { + transform: scale(1); + } + + .zoom-out-in { + transform: scale(1.2); + } +</style> -- Gitblit v1.9.1