mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-06 20:43:46 +08:00
Refactor ambient stars logic and improve CSS for stability and performance
This commit is contained in:
@@ -1,19 +1,40 @@
|
||||
import assert from "node:assert/strict"
|
||||
import { readFile } from "node:fs/promises"
|
||||
import { test } from "node:test"
|
||||
import { spawnAmbientStars } from "../web/js/ambient-stars.js"
|
||||
|
||||
test("ambient stars populate the decorative layer once without changing app content", () => {
|
||||
test("ambient stars populate one lightweight texture per star", () => {
|
||||
const children = []
|
||||
const background = {
|
||||
ownerDocument: { createElement: (tag) => ({ tag, style: {} }) },
|
||||
ownerDocument: { createElement: (tag) => {
|
||||
const style = {}
|
||||
Object.defineProperty(style, "setProperty", { value: (name, value) => { style[name] = value } })
|
||||
return { tag, style }
|
||||
} },
|
||||
querySelector: () => children.find((child) => child.className === "galaxy-hero") || null,
|
||||
appendChild: (child) => children.push(child),
|
||||
}
|
||||
assert.equal(spawnAmbientStars(background, () => 0.5), 14)
|
||||
assert.equal(children.length, 14)
|
||||
assert.deepEqual(children[0], { tag: "i", className: "galaxy-hero",
|
||||
style: { left: "50.00%", top: "50.00%", animationDelay: "2.00s", width: "2px", height: "2px" } })
|
||||
style: { left: "50.00%", top: "50.00%", animationDelay: "2.00s", "--galaxy-star-core": "2px" } })
|
||||
assert.equal(spawnAmbientStars(background, () => 0), 0)
|
||||
assert.equal(children.length, 14)
|
||||
assert.equal(spawnAmbientStars(null), 0)
|
||||
})
|
||||
test("ambient stars use a stable texture without promoting the static backdrop", async () => {
|
||||
const css = await readFile(new URL("../web/css/galaxy.css", import.meta.url), "utf8")
|
||||
const backdrop = css.slice(css.indexOf("#galaxy-bg {"), css.indexOf("#galaxy-bg::before"))
|
||||
const starField = css.slice(css.indexOf("#galaxy-bg::before"), css.indexOf("#galaxy-bg .galaxy-hero"))
|
||||
const star = css.slice(css.indexOf("#galaxy-bg .galaxy-hero {"), css.indexOf("@keyframes galaxy-twinkle"))
|
||||
|
||||
assert.doesNotMatch(backdrop, /will-change|translateZ/)
|
||||
assert.match(starField, /inset: 0/)
|
||||
assert.doesNotMatch(starField, /height:\s*200%/)
|
||||
assert.match(star, /radial-gradient/)
|
||||
assert.doesNotMatch(star, /box-shadow/)
|
||||
assert.match(css, /rotateZ\(0\.05deg\) scale\(0\.9\)/)
|
||||
assert.match(css, /rotateZ\(0\.05deg\) scale\(1\.2\)/)
|
||||
assert.match(css, /body:has\([^)]*\.gx-route-workspace[^)]*\) #galaxy-bg \.galaxy-hero\s*{\s*display: none;/)
|
||||
assert.doesNotMatch(css, /animation-play-state/)
|
||||
})
|
||||
|
||||
@@ -105,7 +105,6 @@
|
||||
|
||||
--content-width: 1200px;
|
||||
--panel-padding: var(--sp-5);
|
||||
--gx-para-x: 0px;
|
||||
}
|
||||
|
||||
[data-theme="light"] {
|
||||
@@ -222,16 +221,18 @@ body {
|
||||
radial-gradient(ellipse at 85% 75%, rgba(85, 45, 180, 0.18) 0%, transparent 60%),
|
||||
radial-gradient(circle at 75% 15%, rgba(77, 232, 232, 0.12) 0%, transparent 48%);
|
||||
pointer-events: none;
|
||||
transform: translateZ(0);
|
||||
will-change: transform;
|
||||
isolation: isolate;
|
||||
contain: strict;
|
||||
}
|
||||
|
||||
#galaxy-bg::before {
|
||||
#galaxy-bg::before,
|
||||
#galaxy-bg::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0; left: 0; width: 100%; height: 200%;
|
||||
inset: 0;
|
||||
}
|
||||
|
||||
#galaxy-bg::before {
|
||||
background-image:
|
||||
radial-gradient(1px 1px at 30px 40px, #ffffff, rgba(255,255,255,0)),
|
||||
radial-gradient(1px 1px at 110px 220px, rgba(220, 200, 255, 0.8), rgba(255,255,255,0)),
|
||||
@@ -242,14 +243,9 @@ body {
|
||||
radial-gradient(1px 1px at 890px 180px, #ffffff, rgba(255,255,255,0));
|
||||
background-size: 800px 400px;
|
||||
opacity: 0.5;
|
||||
will-change: transform;
|
||||
transform: translate3d(var(--gx-para-x), 0, 0);
|
||||
}
|
||||
|
||||
#galaxy-bg::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0; left: 0; width: 100%; height: 200%;
|
||||
background-image:
|
||||
radial-gradient(1.5px 1.5px at 80px 140px, #ffffff, rgba(255,255,255,0)),
|
||||
radial-gradient(2px 2px at 240px 390px, rgba(190, 235, 255, 0.9), rgba(255,255,255,0)),
|
||||
@@ -258,29 +254,29 @@ body {
|
||||
radial-gradient(1.5px 1.5px at 730px 220px, rgba(255, 255, 255, 0.9), rgba(255,255,255,0));
|
||||
background-size: 900px 450px;
|
||||
opacity: 0.6;
|
||||
will-change: transform;
|
||||
transform: translate3d(var(--gx-para-x), 0, 0);
|
||||
}
|
||||
|
||||
#galaxy-bg .galaxy-hero {
|
||||
position: absolute;
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
margin: calc((var(--galaxy-star-core) - 8px) / 2);
|
||||
border-radius: 50%;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 0 6px rgba(255, 255, 255, 0.9);
|
||||
background: radial-gradient(circle,
|
||||
#fff 0 calc(var(--galaxy-star-core) / 2),
|
||||
rgba(255, 255, 255, 0.15) calc(var(--galaxy-star-core) / 2 + 0.3px),
|
||||
rgba(255, 255, 255, 0.04) calc(var(--galaxy-star-core) / 2 + 1.5px),
|
||||
transparent 4px);
|
||||
animation: galaxy-twinkle 6s ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
@keyframes galaxy-twinkle {
|
||||
0%, 100% { opacity: 0.3; transform: scale(0.9); }
|
||||
50% { opacity: 1; transform: scale(1.2); }
|
||||
0%, 100% { opacity: 0.3; transform: rotateZ(0.05deg) scale(0.9); }
|
||||
50% { opacity: 1; transform: rotateZ(0.05deg) scale(1.2); }
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
#galaxy-bg, #galaxy-bg::before, #galaxy-bg::after, #galaxy-bg .galaxy-hero {
|
||||
animation: none !important;
|
||||
}
|
||||
#galaxy-bg .galaxy-hero { animation: none !important; }
|
||||
}
|
||||
|
||||
/* Keep decorative animation out of route viewers, modal backdrops and drawer content. */
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
const STAR_COUNT = 14
|
||||
|
||||
export function spawnAmbientStars(background, random = Math.random) {
|
||||
if (!background || background.querySelector(".galaxy-hero")) return 0
|
||||
for (let index = 0; index < 14; index++) {
|
||||
for (let index = 0; index < STAR_COUNT; index++) {
|
||||
const star = background.ownerDocument.createElement("i")
|
||||
star.className = "galaxy-hero"
|
||||
star.style.left = `${(random() * 100).toFixed(2)}%`
|
||||
star.style.top = `${(random() * 100).toFixed(2)}%`
|
||||
star.style.animationDelay = `${(random() * 4).toFixed(2)}s`
|
||||
star.style.width = star.style.height = random() > 0.6 ? "3px" : "2px"
|
||||
star.style.setProperty("--galaxy-star-core", random() > 0.6 ? "3px" : "2px")
|
||||
background.appendChild(star)
|
||||
}
|
||||
return 14
|
||||
return STAR_COUNT
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user