Skip to content

Commit 9cdec15

Browse files
committed
feat: 行星组件初步功能
1 parent e6e98d4 commit 9cdec15

1 file changed

Lines changed: 154 additions & 0 deletions

File tree

app/components/IntroPlanet.vue

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
<template>
2+
<div
3+
class="relative w-full h-150 md:h-112.5 sm:h-87.5 flex items-center justify-center overflow-hidden bg-[radial-gradient(ellipse_at_center,#1a1a2e_0%,#0f0f1a_100%)]"
4+
>
5+
<div class="absolute inset-0 pointer-events-none">
6+
<div
7+
v-for="star in stars"
8+
:key="star.id"
9+
class="absolute rounded-full bg-white animate-pulse opacity-70"
10+
:style="{
11+
left: star.left,
12+
top: star.top,
13+
width: star.size,
14+
height: star.size,
15+
animationDelay: star.animationDelay,
16+
animationDuration: star.animationDuration,
17+
}"
18+
/>
19+
</div>
20+
21+
<div class="relative w-full h-full flex items-center justify-center">
22+
<div class="absolute w-12 h-12 z-10">
23+
<div
24+
class="absolute inset-0 rounded-full shadow-[0_0_20px_#ffd700,0_0_40px_#ffa500,0_0_60px_#ff8c00] animate-[pulse_4s_ease-in-out_infinite]"
25+
style="background: radial-gradient(circle at 30% 30%, #fff5c0, #ffd700, #ff8c00);"
26+
/>
27+
<div
28+
class="absolute inset-[-25%] rounded-full animate-pulse"
29+
style="background: radial-gradient(circle, rgba(255, 215, 0, 0.3) 0%, transparent 70%); animation-duration: 3s;"
30+
/>
31+
</div>
32+
33+
<div class="relative w-full h-full flex items-center justify-center">
34+
<div
35+
v-for="(planet, index) in planets"
36+
:key="planet.name"
37+
class="absolute rounded-full pointer-events-none"
38+
:style="getOrbitStyle(index)"
39+
>
40+
<div
41+
class="absolute inset-0 animate-spin"
42+
:style="{ animationDuration: planet.period }"
43+
>
44+
<div
45+
class="absolute top-1/2 left-1/2 cursor-pointer transition-transform duration-300 ease-in-out hover:scale-125"
46+
:style="getPlanetStyle(planet, index)"
47+
@mouseenter="hoveredPlanet = planet.name"
48+
@mouseleave="hoveredPlanet = null"
49+
>
50+
<div
51+
class="relative rounded-full shadow-[inset_-3px_-3px_10px_rgba(0,0,0,0.4),0_0_10px_rgba(255,255,255,0.1)] transition-shadow duration-300 ease-in-out"
52+
:style="{ background: planet.color, width: '100%', height: '100%' }"
53+
>
54+
<div
55+
v-if="planet.name === '土星'"
56+
class="absolute left-1/2 top-1/2 h-[40%] w-[180%] rounded-full border border-white/50 pointer-events-none"
57+
style="transform: translate(-50%, -50%) rotateX(75deg);"
58+
/>
59+
</div>
60+
</div>
61+
</div>
62+
63+
<div
64+
class="absolute inset-0 border border-white/10 rounded-full opacity-70 animate-pulse"
65+
:style="{ animationDuration: planet.period }"
66+
/>
67+
</div>
68+
</div>
69+
</div>
70+
71+
<Transition
72+
enter-from-class="opacity-0"
73+
enter-active-class="transition-opacity duration-300"
74+
leave-to-class="opacity-0"
75+
leave-active-class="transition-opacity duration-300"
76+
>
77+
<div
78+
v-if="hoveredPlanet"
79+
class="absolute bottom-10 left-1/2 -translate-x-1/2 rounded-2xl border border-white/10 bg-black/70 backdrop-blur-xl px-6 py-4 text-center text-white"
80+
>
81+
<div class="text-lg font-semibold">
82+
{{ hoveredPlanet }}
83+
</div>
84+
<div class="mt-2 text-sm text-white/70">
85+
{{ getPlanetInfo(hoveredPlanet) }}
86+
</div>
87+
</div>
88+
</Transition>
89+
</div>
90+
</template>
91+
92+
<script setup lang="ts">
93+
const hoveredPlanet = ref<string | null>(null);
94+
95+
const planets = [
96+
{ name: '1', color: 'radial-gradient(circle at 30% 30%, #b5b5b5, #8c8c8c)', size: 8, period: '8s' },
97+
{ name: '2', color: 'radial-gradient(circle at 30% 30%, #ffd700, #daa520)', size: 12, period: '12s' },
98+
{ name: '3', color: 'radial-gradient(circle at 30% 30%, #4a90d9, #2e5a1c)', size: 14, period: '16s' },
99+
{ name: '4', color: 'radial-gradient(circle at 30% 30%, #ff6b4a, #c1440e)', size: 10, period: '20s' },
100+
{ name: '5', color: 'radial-gradient(circle at 30% 30%, #d4a574, #b8860b)', size: 28, period: '28s' },
101+
{ name: '6', color: 'radial-gradient(circle at 30% 30%, #f4d58d, #d4a574)', size: 24, period: '36s' },
102+
{ name: '7', color: 'radial-gradient(circle at 30% 30%, #7de3f4, #4fa4b5)', size: 18, period: '48s' },
103+
];
104+
105+
const stars = Array.from({ length: 100 }, (_, i) => {
106+
const size = Math.random() * 2 + 1;
107+
const x = Math.random() * 100;
108+
const y = Math.random() * 100;
109+
const delay = Math.random() * 3;
110+
const duration = Math.random() * 2 + 1;
111+
return {
112+
id: i,
113+
left: `${x}%`,
114+
top: `${y}%`,
115+
size: `${size}px`,
116+
animationDelay: `${delay}s`,
117+
animationDuration: `${duration}s`,
118+
};
119+
});
120+
121+
function getOrbitStyle(index: number) {
122+
const baseRadius = 60;
123+
const radiusIncrement = 45;
124+
const radius = baseRadius + index * radiusIncrement;
125+
return {
126+
width: `${radius * 2}px`,
127+
height: `${radius * 2}px`,
128+
};
129+
}
130+
131+
function getPlanetStyle(planet: typeof planets[0], index: number) {
132+
const baseRadius = 60;
133+
const radiusIncrement = 45;
134+
const radius = baseRadius + index * radiusIncrement;
135+
return {
136+
width: `${planet.size}px`,
137+
height: `${planet.size}px`,
138+
transform: `translate(-50%, -50%) translateX(${radius}px)`,
139+
};
140+
}
141+
142+
function getPlanetInfo(name: string) {
143+
const info: Record<string, string> = {
144+
1: '1',
145+
2: '2',
146+
3: '3',
147+
4: '4',
148+
5: '5',
149+
6: '6',
150+
7: '7',
151+
};
152+
return info[name] || '';
153+
}
154+
</script>

0 commit comments

Comments
 (0)