Files
----/前端源码/uni-app/components/MysticLoading.vue

318 lines
7.7 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<transition name="mystic-loading">
<div v-if="isOpen" class="mystic-loading-overlay">
<!-- 背景 -->
<div class="mystic-loading-bg"></div>
<!-- 主要内容 -->
<div class="mystic-loading-content">
<!-- 八卦罗盘 -->
<div class="mystic-compass">
<!-- 外圈 - 八卦符号 -->
<div class="mystic-compass-outer">
<svg class="mystic-compass-bagua" viewBox="0 0 200 200">
<!-- 八卦符号 -->
<g class="bagua-symbol" v-for="(gua, i) in bagua" :key="i"
:transform="`rotate(${i * 45} 100 100)`">
<text x="100" y="30" text-anchor="middle" class="bagua-text">{{ gua }}</text>
</g>
</svg>
</div>
<!-- 中圈 - 天干地支 -->
<div class="mystic-compass-middle">
<svg class="mystic-compass-tiangan" viewBox="0 0 200 200">
<g class="tiangan-symbol" v-for="(tg, i) in tiangan" :key="i"
:transform="`rotate(${i * 36} 100 100)`">
<text x="100" y="50" text-anchor="middle" class="tiangan-text">{{ tg }}</text>
</g>
</svg>
</div>
<!-- 内圈 - 太极图 -->
<div class="mystic-compass-inner">
<svg class="mystic-taiji" viewBox="0 0 100 100">
<defs>
<clipPath id="yin">
<path d="M 50 0 A 50 50 0 0 1 50 100 A 25 25 0 0 1 50 50 A 25 25 0 0 0 50 0 Z" />
</clipPath>
<clipPath id="yang">
<path d="M 50 0 A 50 50 0 0 0 50 100 A 25 25 0 0 0 50 50 A 25 25 0 0 1 50 0 Z" />
</clipPath>
</defs>
<!-- -->
<circle cx="50" cy="50" r="50" fill="#2c2c2c" clip-path="url(#yin)" />
<circle cx="50" cy="75" r="5" fill="#fdfbf7" />
<!-- -->
<circle cx="50" cy="50" r="50" fill="#fdfbf7" clip-path="url(#yang)" />
<circle cx="50" cy="25" r="5" fill="#2c2c2c" />
</svg>
</div>
</div>
<!-- 加载文字 -->
<div class="mystic-loading-text">
<div class="mystic-loading-title">{{ title }}</div>
<div class="mystic-loading-subtitle">{{ subtitle }}</div>
<div class="mystic-loading-tip">分析时间预计1-2分钟可点击返回按钮退出并在我的方案中查看结果</div>
</div>
<!-- 进度提示 -->
<div class="mystic-loading-dots">
<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>
</div>
</div>
</div>
</transition>
</template>
<script setup lang="ts">
interface Props {
isOpen: boolean;
title?: string;
subtitle?: string;
}
withDefaults(defineProps<Props>(), {
title: '正在推演命盘',
subtitle: '易经数理 · 五行生克 · 三才五格'
});
// 八卦符号
const bagua = ['☰', '☱', '☲', '☳', '☴', '☵', '☶', '☷'];
// 天干
const tiangan = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸'];
</script>
<style scoped>
.mystic-loading-overlay {
position: fixed;
inset: 0;
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
background: #0a0a0a;
}
.mystic-loading-bg {
position: absolute;
inset: 0;
background: radial-gradient(circle at center, rgba(139, 35, 35, 0.1) 0%, transparent 70%);
animation: pulse 3s ease-in-out infinite;
}
@keyframes pulse {
0%,
100% {
opacity: 0.5;
}
50% {
opacity: 1;
}
}
.mystic-loading-content {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
gap: 40px;
}
/* 罗盘容器 */
.mystic-compass {
position: relative;
width: 280px;
height: 280px;
display: flex;
align-items: center;
justify-content: center;
}
/* 外圈 - 八卦 */
.mystic-compass-outer {
position: absolute;
width: 100%;
height: 100%;
animation: rotate-clockwise 20s linear infinite;
}
.mystic-compass-bagua {
width: 100%;
height: 100%;
filter: drop-shadow(0 0 10px rgba(139, 35, 35, 0.5));
}
.bagua-text {
font-size: 24px;
fill: #8b2323;
font-family: SimSun, "Songti SC", serif;
font-weight: bold;
}
/* 中圈 - 天干 */
.mystic-compass-middle {
position: absolute;
width: 70%;
height: 70%;
animation: rotate-counter-clockwise 15s linear infinite;
}
.mystic-compass-tiangan {
width: 100%;
height: 100%;
filter: drop-shadow(0 0 8px rgba(218, 165, 32, 0.4));
}
.tiangan-text {
font-size: 18px;
fill: #daa520;
font-family: SimSun, "Songti SC", serif;
font-weight: bold;
}
/* 内圈 - 太极 */
.mystic-compass-inner {
position: absolute;
width: 35%;
height: 35%;
animation: rotate-clockwise 10s linear infinite;
filter: drop-shadow(0 0 15px rgba(255, 255, 255, 0.3));
}
.mystic-taiji {
width: 100%;
height: 100%;
}
@keyframes rotate-clockwise {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@keyframes rotate-counter-clockwise {
from {
transform: rotate(0deg);
}
to {
transform: rotate(-360deg);
}
}
/* 加载文字 */
.mystic-loading-text {
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
}
.mystic-loading-title {
font-size: 24px;
font-weight: bold;
color: #fdfbf7;
font-family: SimSun, "Songti SC", serif;
letter-spacing: 0.3em;
text-shadow: 0 0 20px rgba(139, 35, 35, 0.8);
}
.mystic-loading-subtitle {
font-size: 14px;
color: #8a8a8a;
font-family: SimSun, "Songti SC", serif;
letter-spacing: 0.2em;
}
.mystic-loading-tip {
margin-top: 10px;
max-width: min(520px, 86vw);
text-align: center;
font-size: 12px;
line-height: 1.6;
color: rgba(226, 226, 226, 0.72);
letter-spacing: 0.06em;
font-family: SimSun, "Songti SC", serif;
}
/* 加载点 */
.mystic-loading-dots {
display: flex;
gap: 8px;
align-items: center;
}
.dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #8b2323;
animation: dot-pulse 1.4s ease-in-out infinite;
}
.dot:nth-child(1) {
animation-delay: 0s;
}
.dot:nth-child(2) {
animation-delay: 0.2s;
}
.dot:nth-child(3) {
animation-delay: 0.4s;
}
@keyframes dot-pulse {
0%,
80%,
100% {
opacity: 0.3;
transform: scale(0.8);
}
40% {
opacity: 1;
transform: scale(1.2);
}
}
/* 过渡动画 */
.mystic-loading-enter-active,
.mystic-loading-leave-active {
transition: opacity 0.5s;
}
.mystic-loading-enter-from,
.mystic-loading-leave-to {
opacity: 0;
}
.mystic-loading-enter-active .mystic-compass {
animation: compass-enter 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes compass-enter {
from {
transform: scale(0) rotate(-180deg);
opacity: 0;
}
to {
transform: scale(1) rotate(0deg);
opacity: 1;
}
}
</style>