vue3 数据大屏 项目开发中,需要弹窗组件,这里我们整理弹窗组件,并通过gsap补间动画给弹窗添加入场动画以及离场动画。
弹窗效果
弹窗动画
展开动画:从中间缓慢向上下两边展开;
收缩动画:从上下两边向中间收缩隐藏。
效果截图
演示动画
使用组件
组件可传值宽高控制大小。标题宽度随内部文字的多少而变化。
<template>
<div class="popBody">
<el-button @click="getShow" type="primary">弹窗</el-button>
<pop ref="pop" width="300px" height="500px">
dsfsdfsd
</pop>
</div>
</template>
<script>
import pop from './pop.vue'
export default {
data() {
return {}
},
components: {pop},
computed: {},
methods: {
getShow() {
this.$refs.pop.getShow()
}
},
}
</script>
<style lang="scss" scoped>
.popBody {
position: relative;
width: 100%;
height: 100%;
}
</style>
组件代码
<template>
<div>
<div class="popWin" v-if="show">
<div class="popWinBg" v-if="show"></div>
<div class="popWinMain" :style="{height:height}" ref="popWinMain" v-if="show">
<div class="popWinMainInner">
<bg></bg>
<div class="titleBody" ref="titleBody">
<div class="titleBody1"></div>
<div class="titleBody2">
<span>{{ title }}</span>
</div>
<div class="titleBody3"></div>
</div>
<div class="popClose" ref="popClose" v-if="showInner" @click="getHide"></div>
<div class="slot" v-if="showInner">
<slot></slot>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import gsap from 'gsap'
import bg from './bg.vue'
export default {
data() {
return {
show: false,
showInner: false
}
},
components: {bg},
computed: {},
mounted() {
},
props: {
title: {
type: String,
default() {
return '标题';
}
},
width: {
type: String,
default() {
return '458px';
}
},
height: {
type: String,
default() {
return '240px';
}
},
},
methods: {
getShow() {
var that = this;
that.show = true
that.$nextTick(() => {
gsap.to(this.$refs.popWinMain, {
duration: 1, width: this.width, onComplete: () => {
this.showInner = true
this.$nextTick(() => {
gsap.to(this.$refs.popClose, {
duration: 1, transform: ' rotateY(180deg)', onComplete: () => {
this.showInner = true
}
})
gsap.to(this.$refs.titleBody, {
duration: 1, top: '0px', onComplete: () => {
this.showInner = true
}
})
})
}
})
})
},
getHide() {
this.showInner = false
gsap.to(this.$refs.titleBody, {
duration: 0.5, top: '-100px', opacity: 0, onComplete: () => {
// this.showInner = true
}
})
this.$nextTick(() => {
gsap.to(this.$refs.popWinMain, {
duration: 1, width: '0%', onComplete: () => {
this.show = false
}
})
})
}
},
}
</script>
<style lang="scss" scoped>
.popWinBg {
position: fixed;
z-index: 8;
width: 100%;
background: rgba(0, 0, 0, 0.4);
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: initial;
}
.titleBody {
//background: url("./assets/titlebg.png") center center no-repeat;
margin: auto;
//background-size: 100% 100%;
width: auto;
height: 37px;
position: relative;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
align-content: flex-start;
top: -100px;
opacity: 1;
z-index: 0;
.titleBody1 {
width: 21px;
height: 37px;
background: url("./assets/titlebg1.png") no-repeat;
}
.titleBody2 {
height: 37px;
background: url("./assets/titlebg2.png") no-repeat;
background-size: 100% 100%;
min-width: 200px;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
align-content: flex-start;
span {
font-size: 24px;
font-family: PangMenZhengDao;
font-weight: 400;
color: rgba(26, 228, 248, 1.00);
}
}
.titleBody3 {
width: 21px;
height: 37px;
background: url("./assets/titlebg3.png") no-repeat;
}
}
.popWin {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
align-content: flex-start;
position: fixed;
z-index: 10;
width: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
height: 100%;
pointer-events: none;
}
.popWinMainInner {
pointer-events: initial;
position: relative;
width: calc(100% - 50px);
height: calc(100% - 50px);
}
.popWinMain {
pointer-events: initial;
position: relative;
overflow: hidden;
width: 0;
max-width: 1642px;
height: 92%;
max-height: 1004px;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
align-content: flex-start;
z-index: 100;
.slot {
position: absolute;
top: 80px;
left: 30px;
width: calc(100% - 60px);
height: calc(100% - 100px);
//background: red;
}
}
.popClose {
position: absolute;
right: 0px;
top: 0px;
background: url("./assets/icon_close.png") no-repeat;
width: 64px;
height: 64px;
background-size: 100% 100%;
cursor: pointer;
z-index: 1;
}
</style>
组件抽离
弹窗的边框样式可以抽离出来,用作大屏的小边框样式:vue3 数据可视化大屏蓝色边框-四角加梯形标题样式
更多数据可视化大屏弹窗
弹窗完整实例代码
项目基于Vue3 vite js nodejs 14