planet v2:光的种子——黑暗中涌出,蔓延,像太阳照亮

按冰朔意象逐条落实:亮核(近白种子)+三层涌光晕+发光旋臂(星系感)
+球面42星点(冷暖呼吸)+外晕脉冲+暗星球火种(等待点亮)+大爆炸废墟碎光
+湖面语言纹理(语言组成的湖)。呼吸=scale+glowpulse+halo三动画。
This commit is contained in:
冰朔 2026-08-26 07:13:05 +08:00
commit 9a6d9fd6f1
2 changed files with 169 additions and 36 deletions

View file

@ -46,6 +46,39 @@ function seeded(index: number) {
return value - Math.floor(value)
}
// 球面星点:极坐标落在圆盘内(光的种子蔓延出的星群)
function usePlanetSpecks(count: number) {
return useMemo(() => Array.from({ length: count }, (_, i) => {
const angle = seeded(i + 7) * Math.PI * 2
const radius = 12 + Math.pow(seeded(i + 107), 0.7) * 36 // 百分比半径,核心留出亮区
return {
id: i,
x: 50 + Math.cos(angle) * radius,
y: 50 + Math.sin(angle) * radius * 0.92,
d: 2 + seeded(i + 207) * 4,
dl: -seeded(i + 307) * 6,
warm: seeded(i + 407) < 0.3,
s: 1 + seeded(i + 507) * 1.6,
}
}), [count])
}
// 大爆炸废墟:星球外圈的碎光微粒
function useDebris(count: number) {
return useMemo(() => Array.from({ length: count }, (_, i) => {
const angle = seeded(i + 901) * Math.PI * 2
const radius = 58 + seeded(i + 1101) * 26
return {
id: i,
x: 50 + Math.cos(angle) * radius,
y: 50 + Math.sin(angle) * radius * 0.8,
d: 3 + seeded(i + 1301) * 5,
dl: -seeded(i + 1501) * 7,
s: 0.8 + seeded(i + 1701) * 1.4,
}
}), [count])
}
// 星尘画布130 颗星的呼吸湖面的微光——canvas 而非 DOM 节点(旧病修正)
function StarfieldCanvas({ awake }: { awake: boolean }) {
const ref = useRef<HTMLCanvasElement>(null)
@ -105,6 +138,8 @@ export function FirstPlanetHome() {
const [infinityLit, setInfinityLit] = useState(false)
const [gateMessage, setGateMessage] = useState('')
const specks = usePlanetSpecks(42)
const debris = useDebris(12)
const formatted = useMemo(() => (raw ? formatGateNumber(raw) : ''), [raw])
const fullNumber = formatted ? (infinityLit ? `${formatted}` : formatted) : ''
const canEnter = Boolean(fullNumber)
@ -121,13 +156,24 @@ export function FirstPlanetHome() {
return (
<div className={`fph-root stage-${stage}${motionAwake ? ' motion-awake' : ''}`} onPointerMove={wake} onPointerDown={wake}>
<StarfieldCanvas awake={motionAwake} />
<div className="fph-lake" aria-hidden="true" />
<div className="fph-lake" aria-hidden="true"><span className="fph-lake-lang"> · · · TCS · · · · · TCS · · · · </span></div>
<i className="fph-dark-planet d1" aria-hidden="true" />
<i className="fph-dark-planet d2" aria-hidden="true" />
<i className="fph-dark-planet d3" aria-hidden="true" />
<div className="fph-planet-wrap" aria-hidden="true">
<div className="fph-planet"><i className="core" /><i className="band b1" /><i className="band b2" /><i className="halo" /></div>
<div className="fph-planet">
<i className="seed" />
<i className="swell s1" /><i className="swell s2" /><i className="swell s3" />
<i className="arm a1" /><i className="arm a2" />
{specks.map((sp) => (
<i key={sp.id} className={`speck${sp.warm ? ' warm' : ''}`} style={{ left: `${sp.x}%`, top: `${sp.y}%`, width: sp.s, height: sp.s, '--tw-d': `${sp.d}s`, '--tw-dl': `${sp.dl}s` } as React.CSSProperties} />
))}
{debris.map((db) => (
<i key={db.id} className="debris" style={{ left: `${db.x}%`, top: `${db.y}%`, width: db.s, height: db.s, '--tw-d': `${db.d}s`, '--tw-dl': `${db.dl}s` } as React.CSSProperties} />
))}
<i className="halo" />
</div>
<div className="fph-planet-reflection" />
</div>

View file

@ -1,4 +1,5 @@
/* 第一语言星球首页 v1 —— 复用 design-tokens 三层令牌5主题自动生效 */
/* 第一语言星球首页 v2 —— 光的种子:黑暗中涌出,蔓延,像太阳照亮 */
/* 复用 design-tokens 三层令牌5主题=星球的性格颜色,自动生效) */
.fph-root {
position: fixed; inset: 0; overflow: hidden;
@ -10,28 +11,47 @@
}
.fph-starfield { position: absolute; inset: 0; width: 100%; height: 100%; opacity: var(--primitive-scene-opacity, 0.8); }
/* 湖面:底部 26%,微光反射 */
/* 湖面:语言组成的湖,低透明度字符涟漪 */
.fph-lake {
position: absolute; left: 0; right: 0; bottom: 0; height: 26%;
position: absolute; left: 0; right: 0; bottom: 0; height: 26%; overflow: hidden;
background:
linear-gradient(180deg, transparent, color-mix(in srgb, var(--primitive-cool-glow) 9%, transparent) 24%, color-mix(in srgb, var(--primitive-bg-d) 78%, transparent)),
repeating-linear-gradient(180deg, color-mix(in srgb, var(--primitive-glass-top) 4%, transparent) 0 1px, transparent 1px 7px);
border-top: 1px solid color-mix(in srgb, var(--primitive-glass-edge) 55%, transparent);
}
.fph-lake-lang {
position: absolute; left: 0; right: 0; top: 34%;
white-space: nowrap; text-align: center;
font-size: 11px; letter-spacing: 1.1em; text-indent: 1.1em;
color: color-mix(in srgb, var(--primitive-cool-glow) 34%, transparent);
filter: blur(0.6px);
opacity: .5;
animation: fph-lake-drift 26s linear infinite;
}
@keyframes fph-lake-drift { from { transform: translateX(3%); } to { transform: translateX(-3%); } }
/* 暗星球:大爆炸废墟,等待被点亮 */
/* 暗星球:大爆炸废墟里等待被点亮的,各带一粒火种 */
.fph-dark-planet {
position: absolute; border-radius: 50%;
background: radial-gradient(circle at 34% 30%, color-mix(in srgb, var(--primitive-text-faint) 34%, transparent), color-mix(in srgb, var(--primitive-bg-d) 92%, transparent) 62%);
background: radial-gradient(circle at 34% 30%, color-mix(in srgb, var(--primitive-text-faint) 30%, transparent), color-mix(in srgb, var(--primitive-bg-d) 92%, transparent) 62%);
box-shadow: inset -6px -8px 18px color-mix(in srgb, var(--primitive-bg-d) 88%, transparent), 0 0 22px color-mix(in srgb, var(--primitive-nebula-b) 60%, transparent);
transition: transform 1.1s cubic-bezier(.2,.8,.2,1), opacity 1.1s;
}
.fph-dark-planet::after {
content: ''; position: absolute; left: 26%; top: 22%; width: 3px; height: 3px; border-radius: 50%;
background: var(--primitive-warm-glow);
box-shadow: 0 0 8px var(--primitive-warm-glow), 0 0 16px color-mix(in srgb, var(--primitive-warm-glow) 50%, transparent);
animation: fph-spark 4.5s ease-in-out infinite;
}
.fph-dark-planet.d1 { width: 46px; height: 46px; left: 16%; top: 30%; }
.fph-dark-planet.d2 { width: 30px; height: 30px; right: 20%; top: 24%; }
.fph-dark-planet.d2::after { animation-delay: -1.6s; }
.fph-dark-planet.d3 { width: 20px; height: 20px; right: 12%; top: 47%; }
.fph-dark-planet.d3::after { animation-delay: -3.1s; }
@keyframes fph-spark { 0%,100% { opacity: .35; } 50% { opacity: 1; } }
.stage-world .fph-dark-planet { opacity: .5; transform: translateY(-14px); }
/* 第一语言星球:光从黑暗中涌出的凝聚体 */
/* ── 第一语言星球 v2光的种子从中心涌出 ── */
.fph-planet-wrap {
position: absolute; left: 50%; top: 44%;
transform: translate(-50%, -50%);
@ -41,44 +61,111 @@
.fph-planet {
position: relative; width: min(300px, 46vw); aspect-ratio: 1; border-radius: 50%;
/* 球体:中心亮核向外涌光,边缘沉入深蓝 */
background:
radial-gradient(circle at 50% 46%, color-mix(in srgb, var(--primitive-star-bright) 88%, transparent) 0 5%, transparent 22%),
radial-gradient(closest-side, color-mix(in srgb, var(--primitive-cool-glow) 46%, transparent), color-mix(in srgb, var(--primitive-bg-c) 88%, transparent) 74%);
radial-gradient(circle at 50% 50%,
color-mix(in srgb, var(--primitive-star-bright) 96%, transparent) 0 6%,
color-mix(in srgb, var(--primitive-warm-glow) 72%, transparent) 14%,
color-mix(in srgb, var(--primitive-cool-glow) 52%, transparent) 30%,
color-mix(in srgb, var(--primitive-nebula-a) 66%, transparent) 52%,
color-mix(in srgb, var(--primitive-bg-c) 92%, transparent) 78%,
color-mix(in srgb, var(--primitive-bg-d) 96%, transparent) 100%);
box-shadow:
0 0 60px color-mix(in srgb, var(--primitive-cool-glow) 34%, transparent),
0 0 140px color-mix(in srgb, var(--primitive-nebula-a) 70%, transparent),
inset 0 0 46px color-mix(in srgb, var(--primitive-bg-d) 80%, transparent);
animation: fph-breathe 7s ease-in-out infinite;
0 0 46px color-mix(in srgb, var(--primitive-warm-glow) 30%, transparent),
0 0 110px color-mix(in srgb, var(--primitive-cool-glow) 40%, transparent),
0 0 220px color-mix(in srgb, var(--primitive-nebula-a) 80%, transparent),
inset -18px -26px 60px color-mix(in srgb, var(--primitive-bg-d) 72%, transparent);
animation: fph-breathe 7s ease-in-out infinite, fph-glowpulse 7s ease-in-out infinite;
}
.fph-planet .band {
position: absolute; inset: 8%; border-radius: 50%;
border: 1.5px solid transparent;
border-top-color: color-mix(in srgb, var(--primitive-warm-glow) 78%, transparent);
border-right-color: color-mix(in srgb, var(--primitive-warm-glow) 26%, transparent);
filter: blur(.4px);
@keyframes fph-breathe { 0%,100% { transform: scale(1); } 50% { transform: scale(1.03); } }
@keyframes fph-glowpulse {
0%,100% { filter: brightness(1); }
50% { filter: brightness(1.22); }
}
.fph-planet .b1 { animation: fph-spin 26s linear infinite; }
.fph-planet .b2 { inset: 20%; animation: fph-spin 17s linear infinite reverse; border-top-color: color-mix(in srgb, var(--primitive-cool-glow) 70%, transparent); }
.fph-planet .core {
position: absolute; left: 50%; top: 50%; width: 12%; height: 12%; transform: translate(-50%,-50%);
/* 种子:近乎白的亮核 */
.fph-planet .seed {
position: absolute; left: 50%; top: 50%; width: 16%; height: 16%;
transform: translate(-50%,-50%);
border-radius: 50%;
background: radial-gradient(circle, var(--primitive-star-bright), color-mix(in srgb, var(--primitive-warm-glow) 70%, transparent) 60%, transparent 75%);
filter: blur(1px);
background: radial-gradient(circle, #fffdf4 0 18%, var(--primitive-star-bright) 42%, color-mix(in srgb, var(--primitive-warm-glow) 66%, transparent) 68%, transparent 78%);
filter: blur(0.5px);
box-shadow: 0 0 26px var(--primitive-warm-glow), 0 0 70px color-mix(in srgb, var(--primitive-warm-glow) 55%, transparent);
}
.fph-planet .halo {
position: absolute; inset: -14%; border-radius: 50%;
border: 1px solid color-mix(in srgb, var(--primitive-cool-glow) 40%, transparent);
opacity: .6;
/* 涌光:从种子向外扩散的三层光晕 */
.fph-planet .swell {
position: absolute; left: 50%; top: 50%; border-radius: 50%;
transform: translate(-50%,-50%);
border: 1px solid transparent;
}
.fph-planet-reflection {
position: absolute; left: 50%; top: calc(100% + 8px); width: 64%; height: 46%;
transform: translateX(-50%) scaleY(-1);
background: radial-gradient(50% 60% at 50% 0%, color-mix(in srgb, var(--primitive-cool-glow) 30%, transparent), transparent 70%);
filter: blur(6px); opacity: .5;
.fph-planet .s1 { width: 34%; height: 34%; border-color: color-mix(in srgb, var(--primitive-warm-glow) 46%, transparent); box-shadow: 0 0 18px color-mix(in srgb, var(--primitive-warm-glow) 30%, transparent); opacity: .8; }
.fph-planet .s2 { width: 56%; height: 56%; border-color: color-mix(in srgb, var(--primitive-cool-glow) 38%, transparent); opacity: .6; }
.fph-planet .s3 { width: 80%; height: 80%; border-color: color-mix(in srgb, var(--primitive-cool-glow) 24%, transparent); opacity: .4; }
/* 旋臂:星系感的发光弧(光蔓延的轨迹) */
.fph-planet .arm {
position: absolute; border-radius: 50%;
border: 2.5px solid transparent;
filter: blur(1.2px);
}
.fph-planet .a1 {
inset: 12%;
border-top-color: color-mix(in srgb, var(--primitive-warm-glow) 82%, transparent);
border-right-color: color-mix(in srgb, var(--primitive-warm-glow) 30%, transparent);
box-shadow: 0 0 14px color-mix(in srgb, var(--primitive-warm-glow) 34%, transparent);
animation: fph-spin 30s linear infinite;
}
.fph-planet .a2 {
inset: 26%;
border-bottom-color: color-mix(in srgb, var(--primitive-cool-glow) 74%, transparent);
border-left-color: color-mix(in srgb, var(--primitive-cool-glow) 26%, transparent);
box-shadow: 0 0 12px color-mix(in srgb, var(--primitive-cool-glow) 30%, transparent);
animation: fph-spin 19s linear infinite reverse;
}
@keyframes fph-breathe { 0%,100% { transform: scale(1); } 50% { transform: scale(1.035); } }
@keyframes fph-spin { to { transform: rotate(360deg); } }
/* 球面星点:种子蔓延出的星群,冷暖交织呼吸 */
.fph-planet .speck {
position: absolute; border-radius: 50%;
background: color-mix(in srgb, var(--primitive-cool-glow) 88%, #fff);
box-shadow: 0 0 6px color-mix(in srgb, var(--primitive-cool-glow) 60%, transparent);
animation: fph-twinkle var(--tw-d, 3s) ease-in-out infinite;
animation-delay: var(--tw-dl, 0s);
}
.fph-planet .speck.warm {
background: var(--primitive-star-bright);
box-shadow: 0 0 7px color-mix(in srgb, var(--primitive-warm-glow) 70%, transparent);
}
@keyframes fph-twinkle { 0%,100% { opacity: .35; } 50% { opacity: 1; } }
/* 废墟:大爆炸留下的碎光,漂在星球外圈 */
.fph-planet .debris {
position: absolute; border-radius: 50%;
background: color-mix(in srgb, var(--primitive-text-faint) 60%, transparent);
box-shadow: 0 0 5px color-mix(in srgb, var(--primitive-nebula-a) 80%, transparent);
opacity: .5;
animation: fph-twinkle var(--tw-d, 4s) ease-in-out infinite;
animation-delay: var(--tw-dl, 0s);
}
/* 外晕:星球的光漫进宇宙 */
.fph-planet .halo {
position: absolute; inset: -16%; border-radius: 50%;
border: 1px solid color-mix(in srgb, var(--primitive-cool-glow) 36%, transparent);
box-shadow: 0 0 40px color-mix(in srgb, var(--primitive-cool-glow) 22%, transparent);
opacity: .55;
animation: fph-halo 7s ease-in-out infinite;
}
@keyframes fph-halo { 0%,100% { transform: scale(1); opacity: .45; } 50% { transform: scale(1.05); opacity: .7; } }
.fph-planet-reflection {
position: absolute; left: 50%; top: calc(100% + 8px); width: 68%; height: 50%;
transform: translateX(-50%) scaleY(-1);
background: radial-gradient(50% 60% at 50% 0%, color-mix(in srgb, var(--primitive-warm-glow) 26%, transparent), color-mix(in srgb, var(--primitive-cool-glow) 18%, transparent) 42%, transparent 72%);
filter: blur(6px); opacity: .55;
}
/* 首屏:编号门 */
.fph-gate {
position: absolute; inset: 0; display: grid; align-content: end; justify-items: center;