lx-music-desktop/src/renderer/components/material/Modal.vue
2022-11-06 15:47:55 +08:00

295 lines
7.9 KiB
Vue

<template>
<teleport :to="teleport">
<div v-if="showModal" ref="dom_container" :class="$style.container">
<transition enter-active-class="animated fadeIn" leave-active-class="animated fadeOut">
<div v-show="showContent" :class="[$style.modal, {[$style.filter]: teleport == '#root'}]" @click="bgClose && close()">
<transition :enter-active-class="inClass" :leave-active-class="outClass" @after-enter="$emit('after-enter', $event)" @after-leave="handleAfterLeave">
<div v-show="showContent" :class="$style.content" :style="contentStyle" @click.stop>
<header :class="$style.header">
<button v-if="closeBtn" type="button" @click="close">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 212.982 212.982" space="preserve">
<use xlink:href="#icon-delete" />
</svg>
</button>
</header>
<slot />
</div>
</transition>
</div>
</transition>
</div>
</teleport>
</template>
<script>
import { getRandom } from '@common/utils/common'
import { nextTick } from '@common/utils/vueTools'
import { appSetting } from '@renderer/store/setting'
export default {
props: {
show: {
type: Boolean,
default: false,
},
closeBtn: {
type: Boolean,
default: true,
},
bgClose: {
type: Boolean,
default: false,
},
teleport: {
type: String,
default: '#root',
},
maxWidth: {
type: String,
default: '76%',
},
minWidth: {
type: String,
default: '280px',
},
maxHeight: {
type: String,
default: '76%',
},
width: {
type: String,
default: 'auto',
},
},
emits: ['after-enter', 'after-leave', 'close'],
data() {
return {
animates: [
[['jackInTheBox', 'flipInX', 'flipInY', 'lightSpeedIn'], ['flipOutX', 'flipOutY', 'lightSpeedOut']],
// [['jackInTheBox', 'lightSpeedIn'], ['lightSpeedOut']],
[['rotateInDownLeft', 'rotateInDownRight', 'rotateInUpLeft', 'rotateInUpRight'], ['rotateOutDownLeft', 'rotateOutDownRight', 'rotateOutUpLeft', 'rotateOutUpRight']],
[['jackInTheBox', 'zoomInDown', 'zoomInUp'], ['zoomOutDown', 'zoomOutUp']],
[['slideInDown', 'slideInLeft', 'slideInRight', 'slideInUp'], ['slideOutDown', 'slideOutLeft', 'slideOutRight', 'slideOutUp']],
// ['flipInX', 'flipOutX'],
// ['flipInY', 'flipOutY'],
// ['lightSpeedIn', 'lightSpeedOut'],
// ['rotateInDownLeft', 'rotateOutDownLeft'],
// ['rotateInDownRight', 'rotateOutDownRight'],
// ['rotateInUpLeft', 'rotateOutUpLeft'],
// ['rotateInUpRight', 'rotateOutUpRight'],
// // ['rollIn', 'rollOut'],
// // ['zoomIn', 'zoomOut'],
// ['zoomInDown', 'zoomOutDown'],
// // ['zoomInLeft', 'zoomOutLeft'],
// // ['zoomInRight', 'zoomOutRight'],
// ['zoomInUp', 'zoomOutUp'],
// ['slideInDown', 'slideOutDown'],
// ['slideInLeft', 'slideOutLeft'],
// ['slideInRight', 'slideOutRight'],
// ['slideInUp', 'slideOutUp'],
// // ['jackInTheBox', 'hinge'],
],
// animateIn: [
// 'flipInX',
// 'flipInY',
// // 'fadeIn',
// // 'bounceIn',
// 'lightSpeedIn',
// 'rotateInDownLeft',
// 'rotateInDownRight',
// 'rotateInUpLeft',
// 'rotateInUpRight',
// 'rollIn',
// 'zoomIn',
// 'zoomInDown',
// 'zoomInLeft',
// 'zoomInRight',
// 'zoomInUp',
// 'slideInDown',
// 'slideInLeft',
// 'slideInRight',
// 'slideInUp',
// 'jackInTheBox',
// ],
// animateOut: [
// 'flipOutX',
// 'flipOutY',
// // 'fadeOut',
// // 'bounceOut',
// 'lightSpeedOut',
// 'rotateOutDownLeft',
// 'rotateOutDownRight',
// 'rotateOutUpLeft',
// 'rotateOutUpRight',
// 'rollOut',
// 'zoomOut',
// 'zoomOutDown',
// 'zoomOutLeft',
// 'zoomOutRight',
// 'zoomOutUp',
// 'slideOutDown',
// 'slideOutLeft',
// 'slideOutRight',
// 'slideOutUp',
// 'hinge',
// ],
inClass: 'animated jackInTheBox',
outClass: 'animated slideOutRight',
showModal: false,
showContent: false,
// ai: 0,
}
},
computed: {
contentStyle() {
return {
maxWidth: this.maxWidth,
minWidth: this.minWidth,
width: this.width,
maxHeight: this.maxHeight,
}
},
},
watch: {
show: {
handler(val) {
if (val) {
// const dom = document.getElementById(this.teleport)
// if (dom) {
// // dom.t
// }
this.setRandomAnimation()
this.showModal = true
nextTick(() => {
this.$refs.dom_container.parentNode.classList.add('show-modal')
this.showContent = true
})
} else {
this.$refs.dom_container?.parentNode.classList.remove('show-modal')
this.showContent = false
}
},
immediate: true,
},
},
mounted() {
this.setRandomAnimation()
},
beforeUnmount() {
this.$refs.dom_container?.parentNode.classList.remove('show-modal')
},
methods: {
setRandomAnimation() {
if (appSetting['common.randomAnimate']) {
const [animIn, animOut] = this.animates[getRandom(0, this.animates.length)]
// const [animIn, animOut] = this.animates[this.ai]
// if (++this.ai >= this.animates.length) this.ai = 0
// console.log(animIn, animOut)
// this.inClass = 'animated ' + animIn
// this.outClass = 'animated ' + animOut
this.inClass = 'animated ' + animIn[getRandom(0, animIn.length)]
this.outClass = 'animated ' + animOut[getRandom(0, animOut.length)]
}
},
close() {
this.$emit('close')
},
handleAfterLeave(event) {
this.$emit('after-leave', event)
this.showModal = false
},
},
}
</script>
<style lang="less" module>
@import '@renderer/assets/styles/layout.less';
.container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 99;
}
.modal {
width: 100%;
height: 100%;
// background-color: rgba(0, 0, 0, .2);
// background-color: rgba(255, 255, 255, .6);
// background-color: var(--color-primary-light-600-alpha-900);
// backdrop-filter: blur(4px);
// backdrop-filter: grayscale(70%);
display: grid;
align-items: center;
justify-items: center;
// will-change: transform;
&.filter {
backdrop-filter: grayscale(70%);
}
// &:before {
// .mixin-after;
// position: absolute;
// left: 0;
// top: 0;
// width: 100%;
// height: 100%;
// background-color: var(--color-000);
// opacity: .6;
// }
}
.content {
position: relative;
border-radius: 4px;
box-shadow: 0 0 4px rgba(0, 0, 0, .25);
overflow: hidden;
// max-height: 80%;
// max-width: 76%;
min-width: 220px;
position: relative;
display: flex;
flex-flow: column nowrap;
z-index: 100;
background-color: var(--color-content-background);
}
.header {
flex: none;
background-color: var(--color-primary-light-100-alpha-100);
display: flex;
align-items: center;
justify-content: flex-end;
height: 18px;
button {
border: none;
cursor: pointer;
padding: 4px 7px;
background-color: transparent;
color: var(--color-primary-dark-500-alpha-500);
outline: none;
transition: background-color 0.2s ease;
line-height: 0;
svg {
height: .7em;
}
&:hover {
background-color: var(--color-primary-dark-100-alpha-600);
}
&:active {
background-color: var(--color-primary-dark-200-alpha-600);
}
}
}
</style>