💫 loading 组件加动画

This commit is contained in:
BTMuli
2023-05-25 21:42:24 +08:00
parent 0408b222dc
commit 9e95fb29b0

View File

@@ -1,52 +1,133 @@
<template> <template>
<div class="loading-div"> <transition enter-from-class="out-enter-from" name="out">
<div class="loading-content"> <div v-show="showOut" class="loading-box">
<div class="loading-title"> <transition enter-from-class="in-enter-from" name="in">
{{ title }} <div v-show="showIn" class="loading-div">
<v-progress-circular v-show="!empty" indeterminate color="#f4d8a8" /> <div class="loading-content">
</div> <div class="loading-title">
<div v-if="subtitle !== ''" class="loading-subtitle"> {{ title }}
{{ subtitle }} <v-progress-circular v-show="!empty" indeterminate color="#f4d8a8" />
</div> </div>
<div v-if="!empty" class="loading-img"> <div v-if="subtitle !== ''" class="loading-subtitle">
<img src="/source/UI/loading.webp" alt="loading"> {{ subtitle }}
</div> </div>
<div v-else class="loading-img"> <div v-if="!empty" class="loading-img">
<img src="/source/UI/empty.webp" alt="empty"> <img src="/source/UI/loading.webp" alt="loading">
</div> </div>
<div v-if="content !== ''" class="loading-text"> <div v-else class="loading-img">
{{ content }} <img src="/source/UI/empty.webp" alt="empty">
</div> </div>
<div v-if="content !== ''" class="loading-text">
{{ content }}
</div>
</div>
</div>
</transition>
</div> </div>
</div> </transition>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
// vue
import { ref, watch } from "vue";
interface LoadingProps { interface LoadingProps {
modelValue: boolean;
title?: string; title?: string;
subtitle?: string; subtitle?: string;
content?: string; content?: string;
empty?: boolean; empty?: boolean;
position?: string;
} }
withDefaults(defineProps<LoadingProps>(), { const showOut = ref(false);
const showIn = ref(false);
const props = withDefaults(defineProps<LoadingProps>(), {
modelValue: false,
title: "加载中", title: "加载中",
subtitle: "", subtitle: "",
content: "", content: "",
empty: false, empty: false,
position: "absolute",
}); });
watch(
() => props.modelValue,
(v) => {
if (v) {
showOut.value = true;
setTimeout(() => {
showIn.value = true;
}, 0);
} else {
showIn.value = false;
setTimeout(() => {
showOut.value = false;
}, 200);
}
},
);
</script> </script>
<style lang="css" scoped> <style lang="css" scoped>
.loading-div { .out-enter-active,
position: v-bind(position); .out-leave-active,
.in-enter-active {
transition: all 0.3s;
}
.in-leave-active {
transition: all 0.5s ease-in-out;
}
.out-enter-from,
.in-enter-from {
opacity: 0;
transform: scale(1.5);
}
.out-enter-to,
.in-enter-to {
opacity: 1;
transform: scale(1);
}
.out-leave-from {
opacity: 1;
}
.out-leave-to {
opacity: 0;
}
.in-leave-from {
opacity: 1;
transform: scale(1);
}
.in-leave-to {
opacity: 0;
transform: scale(0);
}
.loading-box {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background: rgb(0 0 0 / 50%);
backdrop-filter: blur(20px);
z-index: 100;
}
.loading-div {
display: flex; display: flex;
top: 25%;
left: 25%;
width: 50%; width: 50%;
height: 50%; height: 50%;
background: rgb(57 59 64 / 50%); background: rgb(255 255 255 / 10%);
backdrop-filter: blur(10px); box-shadow: 0 0 10px rgb(0 0 0 / 40%);
border-radius: 20px; border-radius: 20px;
} }