Enhance SplashScreen with interactive logo visualization

- Added hover effects to the tap-to-start logo, displaying an audio visualization ring on mouse enter and leave.
- Introduced new CSS styles for the visualization ring and segments, including animations for a dynamic user experience.
- Updated component logic to manage hover state, improving interactivity and engagement on the SplashScreen.
This commit is contained in:
Dorian 2026-02-18 10:42:38 +00:00
parent 2885236707
commit 55a13e0183

View File

@ -105,7 +105,7 @@
>
<div class="tap-to-start-content relative flex items-center justify-center perspective-1000">
<span
class="tap-to-start-text font-archipelago font-extrabold text-[rgba(0,0,0,0.35)] text-6xl sm:text-7xl md:text-8xl lg:text-9xl tracking-widest uppercase whitespace-nowrap select-none transition-opacity duration-300"
class="tap-to-start-text font-archipelago font-extrabold text-6xl sm:text-7xl md:text-8xl lg:text-9xl tracking-widest uppercase whitespace-nowrap select-none transition-opacity duration-300"
:class="{ 'opacity-0': tapStartTransitioning }"
>
Enter the Exit
@ -113,7 +113,21 @@
<div
class="tap-to-start-logo absolute"
:class="{ 'tap-logo-launch': tapStartTransitioning }"
@mouseenter="introLogoHover = true"
@mouseleave="introLogoHover = false"
>
<!-- Audio viz ring - visible on hover -->
<div
class="intro-logo-viz-ring"
:class="{ 'intro-logo-viz-visible': introLogoHover && !tapStartTransitioning }"
>
<div
v-for="i in 48"
:key="i - 1"
class="intro-logo-viz-segment"
:style="{ '--segment-deg': `${((i - 1) / 48) * 360}deg`, '--segment-index': i - 1 }"
></div>
</div>
<ScreensaverLogo />
</div>
</div>
@ -152,6 +166,7 @@ const BLINK_AFTER_TYPING = 1500
const showSplash = ref(true)
const showTapToStart = ref(true)
const tapStartTransitioning = ref(false)
const introLogoHover = ref(false)
const backgroundOpacity = ref(0)
const alienIntroComplete = ref(false)
const fadeAlienIntro = ref(false)
@ -621,17 +636,68 @@ onBeforeUnmount(() => {
position: absolute;
z-index: 0;
pointer-events: none;
color: rgba(0, 0, 0, 0.35);
animation: tap-to-start-text-pulse 4s ease-in-out infinite;
}
@keyframes tap-to-start-text-pulse {
0%, 100% { color: rgba(0, 0, 0, 0.3); }
50% { color: rgba(0, 0, 0, 0.5); }
}
.tap-to-start-logo {
position: relative;
z-index: 1;
}
.tap-to-start-logo {
filter: drop-shadow(0 0 40px rgba(255, 255, 255, 0.15));
overflow: visible;
}
.intro-logo-viz-ring {
position: absolute;
left: 50%;
top: 50%;
width: 1px;
height: 1px;
transform: translate(-50%, -50%);
z-index: 0;
pointer-events: none;
opacity: 0;
transition: opacity 0.35s ease;
--viz-radius: 7rem;
}
.intro-logo-viz-ring.intro-logo-viz-visible {
opacity: 1;
}
.intro-logo-viz-segment {
position: absolute;
left: 50%;
top: 50%;
width: 4px;
height: 24px;
margin-left: -2px;
margin-top: -12px;
background: linear-gradient(to bottom, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0.15));
border-radius: 2px;
transform-origin: center center;
transform: rotate(var(--segment-deg)) translateY(calc(-1 * var(--viz-radius)));
animation: intro-viz-pulse 2.5s ease-in-out infinite;
animation-delay: calc(var(--segment-index, 0) * 0.02s);
}
@keyframes intro-viz-pulse {
0%, 100% { opacity: 0.4; transform: rotate(var(--segment-deg)) translateY(calc(-1 * var(--viz-radius))) scaleY(0.5); }
50% { opacity: 1; transform: rotate(var(--segment-deg)) translateY(calc(-1 * var(--viz-radius))) scaleY(1); }
}
@media (min-width: 640px) {
.intro-logo-viz-ring { --viz-radius: 8rem; }
.intro-logo-viz-segment { height: 26px; margin-top: -13px; }
}
@media (min-width: 768px) {
.intro-logo-viz-ring { --viz-radius: 9rem; }
.intro-logo-viz-segment { height: 28px; margin-top: -14px; }
}
.tap-to-start-logo :deep(.logo-gradient-border) {
width: 12rem;
height: 12rem;
position: relative;
z-index: 1;
}
@media (min-width: 640px) {
.tap-to-start-content {