Files
cn-rdms-web/src/components/custom/wave-bg.vue
2026-03-26 20:18:20 +08:00

649 lines
17 KiB
Vue

<script lang="ts" setup>
import { computed } from 'vue';
import { getPaletteColorByNumber } from '@sa/color';
defineOptions({ name: 'WaveBg' });
interface Props {
/** Theme color */
themeColor: string;
}
const props = defineProps<Props>();
const lightColor = computed(() => getPaletteColorByNumber(props.themeColor, 200));
const accentColor = computed(() => getPaletteColorByNumber(props.themeColor, 300));
const darkColor = computed(() => getPaletteColorByNumber(props.themeColor, 500));
const deepColor = computed(() => getPaletteColorByNumber(props.themeColor, 700));
</script>
<template>
<div
class="power-bg pointer-events-none absolute-lt z-1 size-full overflow-hidden"
:style="{
'--power-light': lightColor,
'--power-accent': accentColor,
'--power-dark': darkColor,
'--power-deep': deepColor
}"
>
<div class="power-bg__base"></div>
<div class="power-bg__aurora power-bg__aurora--left"></div>
<div class="power-bg__aurora power-bg__aurora--right"></div>
<div class="power-bg__curtain power-bg__curtain--left"></div>
<div class="power-bg__curtain power-bg__curtain--right"></div>
<div class="power-bg__grid"></div>
<div class="power-bg__scan"></div>
<div class="power-bg__halo power-bg__halo--top"></div>
<div class="power-bg__halo power-bg__halo--bottom"></div>
<div class="power-bg__particles">
<span class="power-bg__particle power-bg__particle--1"></span>
<span class="power-bg__particle power-bg__particle--2"></span>
<span class="power-bg__particle power-bg__particle--3"></span>
<span class="power-bg__particle power-bg__particle--4"></span>
<span class="power-bg__particle power-bg__particle--5"></span>
<span class="power-bg__particle power-bg__particle--6"></span>
</div>
<div class="power-bg__blob power-bg__blob--top">
<svg height="1337" width="1337" viewBox="0 0 1337 1337">
<defs>
<path
id="power-blob-top"
fill-rule="evenodd"
d="M1337,668.5 C1337,1037.455193874239 1037.455193874239,1337 668.5,1337 C523.6725684305388,1337 337,1236 370.50000000000006,1094 C434.03835568300906,824.6732385973953 0,892.6277623047779 0,668.5000000000001 C0,299.5448061257611 299.5448061257609,0 668.4999999999999,0 C1037.455193874239,0 1337,299.544806125761 1337,668.5Z"
/>
<linearGradient id="power-gradient-top" x1="0.79" y1="0.62" x2="0.21" y2="0.86">
<stop offset="0" :stop-color="lightColor" stop-opacity="0.52" />
<stop offset="1" :stop-color="darkColor" stop-opacity="0.16" />
</linearGradient>
</defs>
<use xlink:href="#power-blob-top" fill="url(#power-gradient-top)" />
</svg>
</div>
<div class="power-bg__blob power-bg__blob--bottom">
<svg height="896" width="968" viewBox="0 0 968 896">
<defs>
<path
id="power-blob-bottom"
fill-rule="evenodd"
d="M896,448 C1142.6325445712241,465.5747656464056 695.2579309733121,896 448,896 C200.74206902668806,896 0,695.2579309733121 0,448.0000000000001 C0,200.74206902668806 200.74206902668791,0 447.99999999999994,0 C695.2579309733121,0 475,418 896,448Z"
/>
<linearGradient id="power-gradient-bottom" x1="0.5" y1="0" x2="0.5" y2="1">
<stop offset="0" :stop-color="darkColor" stop-opacity="0.18" />
<stop offset="1" :stop-color="lightColor" stop-opacity="0.5" />
</linearGradient>
</defs>
<use xlink:href="#power-blob-bottom" fill="url(#power-gradient-bottom)" />
</svg>
</div>
<svg class="power-bg__panel" viewBox="0 0 1440 900" preserveAspectRatio="none" aria-hidden="true">
<defs>
<linearGradient id="power-arc-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" :stop-color="lightColor" stop-opacity="0.42" />
<stop offset="45%" :stop-color="accentColor" stop-opacity="0.22" />
<stop offset="100%" :stop-color="deepColor" stop-opacity="0" />
</linearGradient>
<linearGradient id="power-dash-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" :stop-color="lightColor" stop-opacity="0" />
<stop offset="50%" :stop-color="lightColor" stop-opacity="0.52" />
<stop offset="100%" :stop-color="accentColor" stop-opacity="0" />
</linearGradient>
<linearGradient id="power-skyline-gradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" :stop-color="lightColor" stop-opacity="0.16" />
<stop offset="100%" :stop-color="deepColor" stop-opacity="0.02" />
</linearGradient>
</defs>
<g class="power-bg__panel-arcs">
<path d="M-120 770 C180 570, 430 562, 706 650 S1162 890, 1568 778" />
<path d="M90 120 C368 -4, 706 -2, 988 124 S1362 368, 1536 314" />
<path d="M804 -80 C1012 92, 1130 236, 1160 442 S1110 786, 948 990" />
<path d="M28 520 C214 444, 380 426, 592 468 S950 618, 1188 592 1380 510, 1502 438" />
</g>
<g class="power-bg__panel-dashes">
<path d="M104 214 H324" />
<path d="M104 242 H248" />
<path d="M1078 180 H1298" />
<path d="M1078 208 H1368" />
<path d="M1118 724 H1328" />
</g>
<g class="power-bg__skyline">
<path
d="M0 900 V758 H94 V724 H142 V686 H196 V730 H258 V654 H318 V698 H364 V622 H422 V746 H486 V670 H554 V714 H612 V636 H682 V728 H746 V592 H804 V656 H852 V618 H910 V744 H978 V668 H1042 V710 H1100 V632 H1166 V692 H1236 V606 H1296 V744 H1362 V694 H1410 V760 H1440 V900 Z"
/>
</g>
<g class="power-bg__panel-rings">
<circle cx="1148" cy="642" r="96" />
<circle cx="1148" cy="642" r="156" />
</g>
</svg>
<svg class="power-bg__network" viewBox="0 0 1440 900" preserveAspectRatio="none" aria-hidden="true">
<defs>
<linearGradient id="power-line-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" :stop-color="deepColor" stop-opacity="0" />
<stop offset="35%" :stop-color="accentColor" stop-opacity="0.16" />
<stop offset="65%" :stop-color="lightColor" stop-opacity="0.32" />
<stop offset="100%" :stop-color="deepColor" stop-opacity="0" />
</linearGradient>
<linearGradient id="power-flow-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" :stop-color="accentColor" stop-opacity="0" />
<stop offset="50%" :stop-color="lightColor" stop-opacity="0.7" />
<stop offset="100%" :stop-color="accentColor" stop-opacity="0" />
</linearGradient>
<filter id="power-glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="4" result="blur" />
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<g class="power-bg__lines">
<path d="M50 620 C220 590, 260 520, 420 530 S710 610, 890 540 1170 430, 1390 470" />
<path d="M120 710 C280 660, 390 680, 560 630 S840 500, 1010 530 1240 650, 1410 610" />
<path d="M180 250 C330 210, 420 260, 580 240 S860 150, 1010 180 1210 320, 1370 280" />
<path d="M310 210 L310 576" />
<path d="M780 178 L780 618" />
<path d="M1188 164 L1188 648" />
</g>
<g class="power-bg__flows">
<path d="M50 620 C220 590, 260 520, 420 530 S710 610, 890 540 1170 430, 1390 470" />
<path d="M120 710 C280 660, 390 680, 560 630 S840 500, 1010 530 1240 650, 1410 610" />
<path d="M180 250 C330 210, 420 260, 580 240 S860 150, 1010 180 1210 320, 1370 280" />
</g>
<g class="power-bg__nodes" filter="url(#power-glow)">
<circle cx="240" cy="575" r="4" />
<circle cx="430" cy="530" r="5" />
<circle cx="700" cy="585" r="4" />
<circle cx="1015" cy="530" r="5" />
<circle cx="1180" cy="446" r="4" />
<circle cx="355" cy="230" r="3" />
<circle cx="825" cy="176" r="3" />
<circle cx="310" cy="576" r="4" />
<circle cx="780" cy="618" r="4" />
<circle cx="1188" cy="648" r="6" />
</g>
</svg>
</div>
</template>
<style scoped>
.power-bg {
--power-light: #8fd4ff;
--power-accent: #4da8ff;
--power-dark: #2765d2;
--power-deep: #173a82;
}
.power-bg__base,
.power-bg__aurora,
.power-bg__curtain,
.power-bg__grid,
.power-bg__scan,
.power-bg__halo,
.power-bg__particles,
.power-bg__panel,
.power-bg__network,
.power-bg__blob {
position: absolute;
inset: 0;
}
.power-bg__base {
background:
radial-gradient(circle at 18% 22%, color-mix(in srgb, var(--power-light) 26%, transparent) 0, transparent 32%),
radial-gradient(circle at 82% 16%, color-mix(in srgb, var(--power-accent) 20%, transparent) 0, transparent 28%),
radial-gradient(circle at 74% 72%, color-mix(in srgb, var(--power-dark) 14%, transparent) 0, transparent 34%),
linear-gradient(135deg, rgb(255 255 255 / 20%) 0, transparent 28%, transparent 72%, rgb(255 255 255 / 8%) 100%);
animation: powerPulse 16s ease-in-out infinite alternate;
}
.power-bg__aurora {
border-radius: 50%;
filter: blur(42px);
opacity: 0.42;
mix-blend-mode: screen;
animation: powerAurora 18s ease-in-out infinite alternate;
}
.power-bg__aurora--left {
top: 8%;
left: -10%;
width: 42%;
height: 52%;
background:
linear-gradient(145deg, color-mix(in srgb, var(--power-light) 30%, transparent), transparent 60%),
radial-gradient(circle at 30% 35%, color-mix(in srgb, var(--power-accent) 26%, transparent), transparent 64%);
}
.power-bg__aurora--right {
right: -6%;
bottom: -8%;
width: 44%;
height: 48%;
background:
linear-gradient(200deg, color-mix(in srgb, var(--power-light) 18%, transparent), transparent 62%),
radial-gradient(circle at 52% 42%, color-mix(in srgb, var(--power-dark) 26%, transparent), transparent 68%);
animation-duration: 22s;
}
.power-bg__curtain {
filter: blur(12px);
opacity: 0.48;
mix-blend-mode: screen;
animation: powerCurtain 20s ease-in-out infinite alternate;
}
.power-bg__curtain--left {
left: -8%;
top: 0;
width: 34%;
height: 100%;
background: linear-gradient(
90deg,
color-mix(in srgb, var(--power-light) 24%, transparent) 0,
color-mix(in srgb, var(--power-accent) 16%, transparent) 18%,
transparent 68%
);
mask-image: linear-gradient(180deg, transparent 0, rgb(0 0 0 / 72%) 14%, rgb(0 0 0 / 78%) 88%, transparent 100%);
}
.power-bg__curtain--right {
right: -10%;
top: 6%;
width: 38%;
height: 86%;
background: linear-gradient(
270deg,
color-mix(in srgb, var(--power-light) 22%, transparent) 0,
color-mix(in srgb, var(--power-dark) 14%, transparent) 20%,
transparent 68%
);
mask-image: linear-gradient(180deg, transparent 0, rgb(0 0 0 / 58%) 18%, rgb(0 0 0 / 76%) 84%, transparent 100%);
animation-duration: 24s;
}
.power-bg__grid {
opacity: 0.18;
background-image:
linear-gradient(to right, color-mix(in srgb, var(--power-deep) 10%, transparent) 1px, transparent 1px),
linear-gradient(to bottom, color-mix(in srgb, var(--power-deep) 8%, transparent) 1px, transparent 1px);
background-size: 88px 88px;
mask-image: radial-gradient(circle at center, rgb(0 0 0 / 68%) 0, rgb(0 0 0 / 18%) 58%, transparent 100%);
}
.power-bg__scan {
opacity: 0.2;
background: linear-gradient(
118deg,
transparent 0 36%,
color-mix(in srgb, var(--power-light) 7%, transparent) 43%,
color-mix(in srgb, var(--power-light) 16%, transparent) 49%,
color-mix(in srgb, var(--power-light) 7%, transparent) 56%,
transparent 66%
);
transform: translateX(-18%);
animation: powerSweep 18s ease-in-out infinite;
}
.power-bg__particles {
opacity: 0.92;
}
.power-bg__particle {
position: absolute;
width: 10px;
height: 10px;
border-radius: 50%;
background: color-mix(in srgb, var(--power-light) 76%, white 24%);
box-shadow: 0 0 22px color-mix(in srgb, var(--power-light) 28%, transparent);
animation: powerParticle 10s ease-in-out infinite;
}
.power-bg__particle::after {
content: '';
position: absolute;
inset: -34px -2px;
background: linear-gradient(180deg, color-mix(in srgb, var(--power-light) 14%, transparent), transparent 68%);
opacity: 0.75;
}
.power-bg__particle--1 {
top: 18%;
left: 16%;
animation-delay: -1s;
}
.power-bg__particle--2 {
top: 28%;
right: 18%;
width: 8px;
height: 8px;
animation-delay: -4s;
}
.power-bg__particle--3 {
top: 58%;
left: 24%;
width: 12px;
height: 12px;
animation-delay: -2s;
}
.power-bg__particle--4 {
top: 68%;
right: 26%;
width: 7px;
height: 7px;
animation-delay: -7s;
}
.power-bg__particle--5 {
top: 40%;
left: 72%;
width: 9px;
height: 9px;
animation-delay: -5s;
}
.power-bg__particle--6 {
top: 78%;
left: 62%;
width: 8px;
height: 8px;
animation-delay: -8s;
}
.power-bg__halo {
border-radius: 999px;
filter: blur(30px);
opacity: 0.26;
}
.power-bg__halo--top {
top: 9%;
left: 18%;
width: 36%;
height: 14%;
background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--power-light) 24%, transparent), transparent);
}
.power-bg__halo--bottom {
right: 8%;
bottom: 10%;
width: 32%;
height: 16%;
background: radial-gradient(
circle at center,
color-mix(in srgb, var(--power-accent) 22%, transparent),
transparent 72%
);
}
.power-bg__blob {
animation: powerFloat 18s ease-in-out infinite;
}
.power-bg__blob--top {
top: -900px;
right: -300px;
}
.power-bg__blob--bottom {
bottom: -400px;
left: -200px;
animation-duration: 22s;
animation-direction: alternate-reverse;
}
.power-bg__panel {
width: 100%;
height: 100%;
opacity: 0.84;
}
.power-bg__panel-arcs path,
.power-bg__panel-dashes path,
.power-bg__skyline path,
.power-bg__panel-rings circle {
fill: none;
stroke-linecap: round;
}
.power-bg__panel-arcs path {
stroke: url(#power-arc-gradient);
stroke-width: 2.2;
opacity: 0.9;
}
.power-bg__panel-dashes path {
stroke: url(#power-dash-gradient);
stroke-width: 1.6;
stroke-dasharray: 10 12;
opacity: 0.72;
}
.power-bg__skyline path {
fill: url(#power-skyline-gradient);
stroke: color-mix(in srgb, var(--power-light) 24%, transparent);
stroke-width: 1;
opacity: 0.42;
}
.power-bg__panel-rings circle {
stroke: color-mix(in srgb, var(--power-light) 16%, transparent);
stroke-width: 1;
opacity: 0.18;
animation: powerRing 15s ease-in-out infinite;
}
.power-bg__panel-rings circle:nth-child(2) {
animation-delay: -4s;
}
.power-bg__network {
width: 100%;
height: 100%;
opacity: 0.92;
}
.power-bg__lines path {
fill: none;
stroke: url(#power-line-gradient);
stroke-width: 2;
opacity: 0.84;
}
.power-bg__flows path {
fill: none;
stroke: url(#power-flow-gradient);
stroke-width: 3.2;
stroke-linecap: round;
stroke-dasharray: 22 246;
animation: powerFlow 13s linear infinite;
}
.power-bg__flows path:nth-child(2) {
animation-duration: 15s;
animation-delay: -4s;
}
.power-bg__flows path:nth-child(3) {
stroke-width: 2.6;
animation-duration: 18s;
animation-delay: -7s;
}
.power-bg__nodes circle {
fill: color-mix(in srgb, var(--power-light) 92%, white 8%);
opacity: 0.78;
animation: powerBlink 7s ease-in-out infinite;
}
.power-bg__nodes circle:nth-child(2n) {
animation-duration: 9s;
}
.power-bg__nodes circle:nth-child(3n) {
animation-delay: -2s;
}
@keyframes powerFloat {
0% {
transform: translate3d(0, 0, 0) scale(1);
}
50% {
transform: translate3d(-18px, 14px, 0) scale(1.03);
}
100% {
transform: translate3d(12px, -10px, 0) scale(0.98);
}
}
@keyframes powerPulse {
0% {
opacity: 0.9;
transform: scale(1);
}
100% {
opacity: 1;
transform: scale(1.04);
}
}
@keyframes powerAurora {
0%,
100% {
opacity: 0.28;
transform: translate3d(0, 0, 0) scale(0.98);
}
50% {
opacity: 0.48;
transform: translate3d(18px, -12px, 0) scale(1.04);
}
}
@keyframes powerCurtain {
0% {
opacity: 0.32;
transform: translate3d(0, 0, 0);
}
100% {
opacity: 0.52;
transform: translate3d(18px, 0, 0);
}
}
@keyframes powerSweep {
0% {
opacity: 0.06;
transform: translateX(-18%);
}
50% {
opacity: 0.2;
}
100% {
opacity: 0.06;
transform: translateX(18%);
}
}
@keyframes powerParticle {
0%,
100% {
opacity: 0.48;
transform: translate3d(0, 0, 0) scale(0.94);
}
50% {
opacity: 0.95;
transform: translate3d(0, -10px, 0) scale(1.08);
}
}
@keyframes powerFlow {
0% {
stroke-dashoffset: 0;
}
100% {
stroke-dashoffset: -268;
}
}
@keyframes powerRing {
0%,
100% {
opacity: 0.08;
transform: scale(0.99);
}
50% {
opacity: 0.22;
transform: scale(1.02);
}
}
@keyframes powerBlink {
0%,
100% {
opacity: 0.35;
transform: scale(0.96);
}
50% {
opacity: 0.82;
transform: scale(1.08);
}
}
@media (max-width: 640px) {
.power-bg__blob--top {
top: -1170px;
right: -100px;
}
.power-bg__blob--bottom {
bottom: -760px;
left: -100px;
}
.power-bg__grid {
background-size: 56px 56px;
}
.power-bg__curtain {
opacity: 0.34;
}
.power-bg__particles {
opacity: 0.7;
}
.power-bg__network {
opacity: 0.68;
}
.power-bg__panel {
opacity: 0.52;
}
}
</style>