520 lines
10 KiB
Vue
520 lines
10 KiB
Vue
<template>
|
||
<view class="tm-poups " @click.stop="">
|
||
|
||
<block v-if="position_sv != 'center'">
|
||
<view v-show="value==true&&position_sv != 'center'" class="tm-poup " :class="[
|
||
isFilter?'blur':'',
|
||
position_sv == 'center' ? 'tm-poup-center' : '',
|
||
position_sv !='center'?position_sv:'',
|
||
isClickbled?'isClickbled':''
|
||
]" @click.stop.prevent="overClick" @touchmove.stop.prevent="stopMove" :style="{
|
||
backgroundColor: overColor,
|
||
width:'100%',height:'100%'
|
||
}">
|
||
<!-- 内容 -->
|
||
<!-- <view class="tm-poup-wk bottom">{{ show ? 'on' : 'off'}}</view> -->
|
||
<scroll-view :animation="aniData" @click.stop.prevent="" class="tm-poup-wk dhshiKa" scroll-y="true" :class="[
|
||
position_sv == 'top'?'round-b-' + round:'',
|
||
position_sv == 'bottom'?'round-t-' + round:'',
|
||
position_sv, aniOn ? 'on ' : 'off',
|
||
black_tmeme ? 'grey-darken-5 bk' : bgColor
|
||
]" :style="{
|
||
width: (position_sv == 'top' || position_sv == 'bottom') ? '100%' : width_w,
|
||
height: position_sv == 'right' || position_sv == 'left' ?'100%' : height_h,
|
||
|
||
}">
|
||
<view :class="[clssStyle]" >
|
||
<slot></slot>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
<view class="bottomHeight"></view>
|
||
</block>
|
||
|
||
<view v-if="value===true&&position_sv == 'center'" class="tm-poup " :class="[
|
||
isFilter?'blur':'',
|
||
position_sv == 'center' ? 'tm-poup-center' : ''
|
||
]" @click="overClick" @touchmove.stop.prevent="stopMove" :style="{
|
||
backgroundColor: overColor,
|
||
width:sysInfo.screenWidth+'px',height:'100%'
|
||
}">
|
||
<!-- 内容 -->
|
||
<scroll-view :animation="aniData" @click.stop.prevent="" class="tm-poup-wk " scroll-y="true" :class="[
|
||
`round-${round}`,aniOn ? 'on' : 'off', position_sv,
|
||
black_tmeme ? 'grey-darken-5 bk' : bgColor
|
||
]" :style="{
|
||
width: width_w,
|
||
height: height_h
|
||
}">
|
||
<view :class="[clssStyle]">
|
||
<slot></slot>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
/**
|
||
* poup弹出层
|
||
* @description poup弹出层,上下,左右方向。
|
||
* @property {Boolean} value = [true|false] 使用时value.sync可同步,也可不同步。等同于v-model
|
||
* @property {Boolea} v-model 显示和关闭。
|
||
* @property {String} position = [bottom|top|left|right|center] 方向可选bottom,left,right,top,center
|
||
* @property {Function} change 改变时会调用此函数,参数e等同于v-model和value
|
||
* @property {String|Number} width 宽,位置为left,right是起作用。可以是30%或者数字(单位upx)
|
||
* @property {String|Number} height 宽,位置为top,bottom是起作用。可以是30%或者数字(单位upx)
|
||
* @property {String|Number} round 圆角0-25
|
||
* @property {String|Boolean} black = [true|false] 暗黑模式
|
||
* @property {Boolean} over-close = [true|false] 是否点击遮罩关闭。
|
||
* @property {Boolean} is-filter = [true|false] 是否背景模糊
|
||
* @property {String} clss-style = [] 自定内容的类
|
||
* @property {String} bg-color = [white|blue] 默认:white,白色背景;请填写背景的主题色名称。
|
||
* @property {String} over-color = [] 默认:rgba(0,0,0,0.3), 遮罩层颜色值不是主题。
|
||
* @example <tm-poup height="85%" v-model="show"></tm-poup>
|
||
*/
|
||
export default {
|
||
name: 'tm-poup',
|
||
props: {
|
||
bgColor: {
|
||
type: String,
|
||
default: 'white'
|
||
},
|
||
// 遮罩层颜色。
|
||
overColor: {
|
||
type: String,
|
||
default: 'rgba(0,0,0,0.3)'
|
||
},
|
||
black: {
|
||
type: Boolean | String,
|
||
default: null
|
||
},
|
||
clssStyle: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
value: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
// bottom,left,right,top
|
||
position: {
|
||
type: String,
|
||
default: 'bottom'
|
||
},
|
||
round: {
|
||
type: String | Number,
|
||
default: '10'
|
||
},
|
||
width: {
|
||
type: String | Number,
|
||
default: '30%'
|
||
},
|
||
height: {
|
||
type: String | Number,
|
||
default: 220
|
||
},
|
||
overClose: {
|
||
type: Boolean,
|
||
default: true
|
||
},
|
||
isFilter: {
|
||
type: Boolean,
|
||
default: true,
|
||
},
|
||
//允许穿透背景遮罩。
|
||
isClickbled: {
|
||
type: Boolean,
|
||
default: false
|
||
}
|
||
},
|
||
model: {
|
||
prop: 'value',
|
||
event: 'input',
|
||
sysInfo: {},
|
||
},
|
||
watch: {
|
||
value:function(val){
|
||
this.$emit('change', val);
|
||
if(val){
|
||
this.open()
|
||
}else{this.close()}
|
||
},
|
||
position: function() {
|
||
this.position_sv = this.position
|
||
}
|
||
},
|
||
created() {
|
||
this.sysInfo = uni.getSystemInfoSync();
|
||
},
|
||
computed: {
|
||
black_tmeme: function() {
|
||
if (this.black !== null) return this.black;
|
||
return this.$tm.vx.state().tmVuetify.black;
|
||
},
|
||
width_w: function() {
|
||
let w = this.$TestUnit(this.width);
|
||
let i = w.value;
|
||
if (w.type == 'number') {
|
||
i = w.value + 'px';
|
||
}
|
||
return i;
|
||
},
|
||
height_h: function() {
|
||
let w = this.$TestUnit(this.height);
|
||
let i = w.value;
|
||
if (w.type == 'number') {
|
||
i = w.value + 'px';
|
||
}
|
||
return i;
|
||
},
|
||
|
||
},
|
||
data() {
|
||
return {
|
||
aniOn: false,
|
||
closeTimid: null,
|
||
position_sv: this.position,
|
||
dhshiKa:true,//是否结束动画
|
||
aniData:null,
|
||
timdiiid:6369784254,
|
||
|
||
};
|
||
},
|
||
deactivated() {
|
||
clearTimeout(this.closeTimid)
|
||
},
|
||
destroyed() {
|
||
clearTimeout(this.closeTimid)
|
||
},
|
||
mounted() {
|
||
if(this.value){
|
||
this.open()
|
||
}
|
||
},
|
||
methods: {
|
||
overClick() {
|
||
if (!this.overClose) return;
|
||
this.close();
|
||
},
|
||
close() {
|
||
let t = this;
|
||
clearTimeout(this.timdiiid)
|
||
this.dhshiKa=false;
|
||
t.aniOn=false;
|
||
this.createBtT(this.position_sv,'off').then(()=>{
|
||
t.$emit('input', false);
|
||
t.closeTimid = null;
|
||
t.dhshiKa = true;
|
||
// t.$emit('change', false);
|
||
// console.log('off');
|
||
})
|
||
},
|
||
open() {
|
||
let t = this;
|
||
clearTimeout(this.timdiiid)
|
||
|
||
|
||
this.dhshiKa=false
|
||
this.aniOn=true;
|
||
|
||
this.createBtT(this.position_sv,'on').then(()=>{
|
||
t.dhshiKa=true
|
||
|
||
t.isclick=false
|
||
// console.log('on');
|
||
})
|
||
|
||
},
|
||
//下至上。
|
||
createBtT(pos,type){
|
||
let t = this;
|
||
this.aniData = '';
|
||
let aniData = uni.createAnimation({
|
||
duration:240,
|
||
timingFunction: 'ease',
|
||
})
|
||
this.aniData = aniData;
|
||
if(pos=='bottom'){
|
||
if(type=='on'){
|
||
aniData.translateY('0%').step();
|
||
this.aniData = aniData.export()
|
||
|
||
}
|
||
if(type=='off'){
|
||
aniData.translateY('100%').step();
|
||
this.aniData = aniData.export()
|
||
|
||
}
|
||
}else if(pos=='top'){
|
||
if(type=='on'){
|
||
aniData.translateY('0%').step();
|
||
this.aniData = aniData.export()
|
||
|
||
}
|
||
if(type=='off'){
|
||
aniData.translateY('-100%').step();
|
||
this.aniData = aniData.export()
|
||
|
||
}
|
||
}else if(pos=='left'){
|
||
if(type=='on'){
|
||
aniData.translateX('0%').step();
|
||
this.aniData = aniData.export()
|
||
|
||
}
|
||
if(type=='off'){
|
||
aniData.translateX('-100%').step();
|
||
this.aniData = aniData.export()
|
||
|
||
}
|
||
}else if(pos=='right'){
|
||
if(type=='on'){
|
||
aniData.translateX('0%').step();
|
||
this.aniData = aniData.export()
|
||
|
||
}
|
||
if(type=='off'){
|
||
aniData.translateX('100%').step();
|
||
this.aniData = aniData.export()
|
||
|
||
}
|
||
}else if(pos=='center'){
|
||
|
||
if(type=='on'){
|
||
aniData.opacity(1).scale(1).step();
|
||
this.aniData = aniData.export()
|
||
|
||
}
|
||
if(type=='off'){
|
||
aniData.opacity(0).scale(0.6).step();
|
||
this.aniData = aniData.export()
|
||
|
||
}
|
||
}
|
||
|
||
return new Promise(res=>{
|
||
t.timdiiid = setTimeout(()=>{
|
||
t.aniData = null;
|
||
res();
|
||
},240)
|
||
})
|
||
},
|
||
stopMove(e) {}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.bottomHeight{
|
||
height: var(--window-bottom);
|
||
}
|
||
.tm-poup {
|
||
position: fixed;
|
||
z-index: 452;
|
||
width: 100%;
|
||
height: 100%;
|
||
min-height: 100%;
|
||
min-width: 100%;
|
||
overflow: hidden;
|
||
top: 0;
|
||
left: 0;
|
||
|
||
&.isClickbled {
|
||
pointer-events: none;
|
||
}
|
||
&.okkk{
|
||
pointer-events: none;
|
||
}
|
||
&.blur {
|
||
backdrop-filter: blur(3px);
|
||
}
|
||
|
||
&.on {
|
||
animation: opta 1s ease;
|
||
}
|
||
|
||
&.off {
|
||
animation: opta_off 0.24s ease;
|
||
}
|
||
.tm-poup-wk {
|
||
position: absolute;
|
||
overflow: hidden;
|
||
pointer-events: auto;
|
||
// transition: all 0.3s;
|
||
&.bottom {
|
||
transform: translateY(100%);
|
||
width: 100%;
|
||
bottom: 0;
|
||
|
||
}
|
||
|
||
&.top {
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
transform: translateY(-100%);
|
||
}
|
||
|
||
&.left {
|
||
top: 0;
|
||
transform: translateX(-100%);
|
||
border-radius: 0 !important;
|
||
left: 0;
|
||
}
|
||
|
||
&.right {
|
||
top: 0;
|
||
right: 0;
|
||
transform: translateX(100%);
|
||
border-radius: 0 !important;
|
||
|
||
}
|
||
|
||
&.center {
|
||
opacity:0;
|
||
transform: scale(0.6);
|
||
}
|
||
}
|
||
|
||
&.tm-poup-center {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
align-content: center;
|
||
|
||
|
||
.tm-poup-wk {
|
||
position: static;
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
@keyframes opta {
|
||
from {
|
||
opacity: 0.3;
|
||
}
|
||
|
||
to {
|
||
opacity: 1;
|
||
}
|
||
}
|
||
|
||
@keyframes opta_off {
|
||
from {
|
||
opacity: 1;
|
||
}
|
||
|
||
to {
|
||
opacity: 0;
|
||
}
|
||
}
|
||
|
||
@keyframes bottomTtop {
|
||
from {
|
||
transform: translateY(100%);
|
||
}
|
||
|
||
to {
|
||
transform: translateY(0%);
|
||
}
|
||
}
|
||
|
||
@keyframes bottomTtop_off {
|
||
from {
|
||
transform: translateY(0%);
|
||
}
|
||
|
||
to {
|
||
transform: translateY(100%);
|
||
}
|
||
}
|
||
|
||
@keyframes topTbottom {
|
||
from {
|
||
transform: translateY(-100%);
|
||
}
|
||
|
||
to {
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
@keyframes topTbottom_off {
|
||
from {
|
||
transform: translateY(0);
|
||
}
|
||
|
||
to {
|
||
transform: translateY(-100%);
|
||
}
|
||
}
|
||
|
||
@keyframes leftTright {
|
||
from {
|
||
transform: translateX(-100%);
|
||
}
|
||
|
||
to {
|
||
transform: translateX(0);
|
||
}
|
||
}
|
||
|
||
@keyframes leftTright_off {
|
||
from {
|
||
transform: translateX(0);
|
||
}
|
||
|
||
to {
|
||
transform: translateX(-100%);
|
||
}
|
||
}
|
||
|
||
@keyframes rightTleft {
|
||
from {
|
||
|
||
transform: translateX(100%);
|
||
}
|
||
|
||
to {
|
||
transform: translateX(0%);
|
||
}
|
||
}
|
||
|
||
@keyframes rightTleft_off {
|
||
from {
|
||
transform: translateX(0%);
|
||
}
|
||
|
||
to {
|
||
transform: translateX(100%);
|
||
}
|
||
}
|
||
|
||
@keyframes Centerleft {
|
||
from {
|
||
transform: scale(0.65);
|
||
opacity: 0.3;
|
||
}
|
||
|
||
to {
|
||
transform: scale(1);
|
||
opacity: 1;
|
||
}
|
||
}
|
||
|
||
@keyframes Centerleft_off {
|
||
from {
|
||
transform: scale(1);
|
||
opacity: 1;
|
||
}
|
||
|
||
to {
|
||
transform: scale(0.65);
|
||
opacity: 0.3;
|
||
|
||
}
|
||
}
|
||
</style>
|