perf: replace live oasis background with loop

This commit is contained in:
2026-05-19 16:47:29 +08:00
parent ac4f007985
commit 485982b4ba
2 changed files with 148 additions and 22 deletions

View File

@@ -3,7 +3,7 @@
@tailwind utilities;
html, body {
background: #030603;
background: #071108;
color: #FFFFFF;
font-feature-settings: "cv02", "cv03", "cv04", "cv11", "ss01";
-webkit-font-smoothing: antialiased;
@@ -12,28 +12,135 @@ html, body {
body {
font-family: ui-sans-serif, system-ui, -apple-system, "SF Pro Text", "PingFang SC", "Noto Sans SC", "Helvetica Neue", sans-serif;
background-color: #030603;
background-image: linear-gradient(180deg, rgba(13, 24, 12, 0.9), rgba(2, 4, 2, 1));
background-color: #071108;
background-image: linear-gradient(180deg, rgba(22, 42, 16, 0.92), rgba(5, 12, 4, 1));
background-attachment: fixed;
min-height: 100vh;
}
::selection { background: rgba(230, 245, 120, 0.28); color: #fff; }
.login-oasis-loop {
position: fixed;
inset: 0;
z-index: 0;
overflow: hidden;
pointer-events: none;
isolation: isolate;
contain: strict;
background: #0d1d0b;
}
.oasis-loop__sky,
.oasis-loop__light,
.oasis-loop__haze,
.oasis-loop__grass,
.oasis-loop__grain {
position: absolute;
inset: 0;
pointer-events: none;
}
.oasis-loop__sky {
background:
radial-gradient(circle at 70% 22%, rgba(255, 238, 152, 0.42), transparent 26%),
radial-gradient(circle at 26% 56%, rgba(230, 245, 120, 0.24), transparent 34%),
linear-gradient(180deg, #2f4a23 0%, #172d12 42%, #0a1708 100%);
}
.oasis-loop__light {
inset: -18%;
background:
conic-gradient(from 26deg at 72% 30%, transparent 0 18%, rgba(255, 240, 170, 0.18) 22%, transparent 36% 100%),
radial-gradient(ellipse at 68% 36%, rgba(230, 245, 120, 0.16), transparent 42%);
filter: blur(18px);
opacity: 0.9;
}
.oasis-loop__haze {
inset: -8% -12%;
background:
linear-gradient(104deg, transparent 0 20%, rgba(255, 255, 220, 0.12) 24%, transparent 36% 100%),
linear-gradient(74deg, transparent 0 48%, rgba(214, 179, 106, 0.10) 56%, transparent 70% 100%),
repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.035) 0 1px, transparent 1px 70px);
mix-blend-mode: screen;
opacity: 0.82;
transform: translate3d(-1.5%, 0, 0) scale(1.04);
animation: oasis-haze-loop 18s ease-in-out infinite;
}
.oasis-loop__grass {
top: auto;
bottom: -9vh;
height: 55vh;
transform-origin: 50% 100%;
mask-image: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.7) 20%, #000 100%);
}
.oasis-loop__grass--back {
opacity: 0.46;
background:
linear-gradient(180deg, transparent, rgba(61, 100, 42, 0.38) 34%, rgba(5, 18, 5, 0.94)),
repeating-linear-gradient(102deg, transparent 0 18px, rgba(214, 232, 130, 0.18) 18px 20px, transparent 20px 38px),
repeating-linear-gradient(83deg, transparent 0 24px, rgba(111, 160, 79, 0.22) 24px 26px, transparent 26px 48px);
animation: oasis-grass-loop 9s ease-in-out infinite alternate;
}
.oasis-loop__grass--front {
bottom: -13vh;
height: 49vh;
opacity: 0.58;
background:
linear-gradient(180deg, transparent, rgba(20, 52, 14, 0.46) 32%, rgba(1, 7, 1, 0.98)),
repeating-linear-gradient(107deg, transparent 0 10px, rgba(232, 246, 132, 0.22) 10px 12px, transparent 12px 26px),
repeating-linear-gradient(76deg, transparent 0 16px, rgba(76, 129, 54, 0.28) 16px 18px, transparent 18px 31px);
animation: oasis-grass-loop 7s ease-in-out infinite alternate-reverse;
}
.oasis-loop__grain {
background-image:
linear-gradient(90deg, rgba(255, 255, 255, 0.032) 1px, transparent 1px),
linear-gradient(180deg, rgba(255, 255, 255, 0.026) 1px, transparent 1px);
background-size: 64px 64px;
opacity: 0.48;
}
@keyframes oasis-haze-loop {
0%, 100% { transform: translate3d(-1.5%, 0, 0) scale(1.04); }
50% { transform: translate3d(1.5%, -1%, 0) scale(1.06); }
}
@keyframes oasis-grass-loop {
0% { transform: skewX(-0.6deg) translate3d(-0.5%, 0, 0); }
100% { transform: skewX(0.8deg) translate3d(0.5%, -1%, 0); }
}
@media (prefers-reduced-motion: reduce) {
.oasis-loop__haze,
.oasis-loop__grass {
animation: none;
}
}
.app-oasis .login-oasis-canvas {
z-index: 0;
opacity: 0.74;
filter: saturate(0.92) contrast(1.04);
}
.app-oasis .login-oasis-loop {
opacity: 1;
filter: saturate(1.08) brightness(1.2);
}
.app-oasis-shade {
position: fixed;
inset: 0;
z-index: 1;
pointer-events: none;
background:
linear-gradient(90deg, rgba(0, 0, 0, 0.76), rgba(3, 9, 3, 0.46) 42%, rgba(0, 0, 0, 0.72)),
linear-gradient(180deg, rgba(0, 0, 0, 0.68), rgba(0, 0, 0, 0.12) 36%, rgba(0, 0, 0, 0.82)),
linear-gradient(90deg, rgba(0, 0, 0, 0.42), rgba(9, 22, 7, 0.14) 42%, rgba(0, 0, 0, 0.42)),
linear-gradient(180deg, rgba(0, 0, 0, 0.28), rgba(0, 0, 0, 0.02) 36%, rgba(0, 0, 0, 0.54)),
linear-gradient(90deg, rgba(255, 255, 255, 0.026) 1px, transparent 1px),
linear-gradient(180deg, rgba(255, 255, 255, 0.022) 1px, transparent 1px);
background-size: auto, auto, 64px 64px, 64px 64px;
@@ -47,11 +154,11 @@ body {
z-index: 2;
height: 34vh;
pointer-events: none;
opacity: 0.38;
opacity: 0.46;
background:
linear-gradient(180deg, transparent, rgba(5, 12, 4, 0.78) 60%, rgba(0, 0, 0, 0.94)),
repeating-linear-gradient(103deg, transparent 0 13px, rgba(188, 218, 112, 0.13) 13px 14px, transparent 14px 28px),
repeating-linear-gradient(78deg, transparent 0 18px, rgba(84, 122, 67, 0.18) 18px 20px, transparent 20px 34px);
linear-gradient(180deg, transparent, rgba(10, 25, 7, 0.62) 60%, rgba(0, 0, 0, 0.82)),
repeating-linear-gradient(103deg, transparent 0 13px, rgba(204, 230, 120, 0.18) 13px 14px, transparent 14px 28px),
repeating-linear-gradient(78deg, transparent 0 18px, rgba(98, 146, 76, 0.22) 18px 20px, transparent 20px 34px);
mask-image: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.8) 38%, #000 100%);
}
@@ -256,7 +363,7 @@ input, textarea {
mix-blend-mode: screen;
}
.login-page--oasis {
background: #030303;
background: #071108;
color: #fff;
}
.login-page--oasis::before {
@@ -270,8 +377,8 @@ input, textarea {
.login-page--oasis::after {
z-index: 1;
background:
radial-gradient(circle at 50% 26%, rgba(214, 179, 106, 0.16), transparent 32%),
linear-gradient(90deg, rgba(0, 0, 0, 0.86), rgba(0, 0, 0, 0.34) 48%, rgba(0, 0, 0, 0.76));
radial-gradient(circle at 50% 26%, rgba(230, 245, 120, 0.18), transparent 32%),
linear-gradient(90deg, rgba(0, 0, 0, 0.58), rgba(0, 0, 0, 0.18) 48%, rgba(0, 0, 0, 0.48));
background-size: auto;
opacity: 1;
mix-blend-mode: normal;
@@ -283,7 +390,7 @@ input, textarea {
width: 100vw;
height: 100vh;
border: 0;
background: #030303;
background: #071108;
}
.login-oasis-shade {
position: fixed;
@@ -291,8 +398,8 @@ input, textarea {
z-index: 2;
pointer-events: none;
background:
linear-gradient(180deg, rgba(0, 0, 0, 0.62), rgba(0, 0, 0, 0.12) 42%, rgba(0, 0, 0, 0.74)),
radial-gradient(circle at 78% 50%, rgba(214, 179, 106, 0.12), transparent 32%);
linear-gradient(180deg, rgba(0, 0, 0, 0.42), rgba(0, 0, 0, 0.04) 42%, rgba(0, 0, 0, 0.58)),
radial-gradient(circle at 78% 50%, rgba(230, 245, 120, 0.14), transparent 32%);
}
.login-page--oasis .login-oasis-hero {
color: #fff;
@@ -471,8 +578,8 @@ input, textarea {
}
.login-page--source .login-oasis-shade {
background:
radial-gradient(circle at 34% 52%, rgba(230, 245, 120, 0.08), transparent 28%),
linear-gradient(90deg, rgba(0, 0, 0, 0.22), rgba(0, 0, 0, 0.04) 44%, rgba(0, 0, 0, 0.38));
radial-gradient(circle at 34% 52%, rgba(230, 245, 120, 0.14), transparent 28%),
linear-gradient(90deg, rgba(0, 0, 0, 0.12), rgba(0, 0, 0, 0.02) 44%, rgba(0, 0, 0, 0.24));
}
.login-source-overlay {
position: fixed;
@@ -1696,12 +1803,12 @@ input, textarea {
background: linear-gradient(164deg, #f7f7f4 0 48%, #111214 48% 100%);
}
.login-page--oasis {
background: #030303;
background: #071108;
}
.login-page--oasis::after {
background:
radial-gradient(circle at 50% 34%, rgba(214, 179, 106, 0.16), transparent 40%),
linear-gradient(180deg, rgba(0, 0, 0, 0.72), rgba(0, 0, 0, 0.2) 48%, rgba(0, 0, 0, 0.82));
radial-gradient(circle at 50% 34%, rgba(230, 245, 120, 0.18), transparent 40%),
linear-gradient(180deg, rgba(0, 0, 0, 0.48), rgba(0, 0, 0, 0.08) 48%, rgba(0, 0, 0, 0.62));
}
.login-page--oasis .login-oasis-hero {
min-height: 740px;

View File

@@ -2,10 +2,16 @@
import { useEffect, useRef } from 'react';
export function OasisCanvas() {
type OasisCanvasProps = {
mode?: 'loop' | 'live';
};
export function OasisCanvas({ mode = 'loop' }: OasisCanvasProps) {
const frameRef = useRef<HTMLIFrameElement | null>(null);
useEffect(() => {
if (mode !== 'live') return;
const dispatchNativeMouseEvent = (type: 'mousemove' | 'mouseleave', event?: PointerEvent) => {
const frameWindow = frameRef.current?.contentWindow;
if (!frameWindow) return false;
@@ -52,7 +58,20 @@ export function OasisCanvas() {
document.removeEventListener('pointermove', onPointerMove, listenerOptions);
window.removeEventListener('pointerleave', onPointerLeave, listenerOptions);
};
}, []);
}, [mode]);
if (mode === 'loop') {
return (
<div aria-hidden="true" className="login-oasis-loop">
<div className="oasis-loop__sky" />
<div className="oasis-loop__light" />
<div className="oasis-loop__haze" />
<div className="oasis-loop__grass oasis-loop__grass--back" />
<div className="oasis-loop__grass oasis-loop__grass--front" />
<div className="oasis-loop__grain" />
</div>
);
}
return (
<iframe