fix: 视觉自查修复9处 — 无头浏览器截图验证

通过playwright-core+系统Edge截图自查发现并修复:
1. glowTexture缺省size致createRadialGradient(NaN)全场景崩溃
2. 主光源在月背=月面纯剪影 → 改前左上(参考图光向)
3. 碎石死黑 → 冷补光fillCold
4. 裂缝像荧光管 → 减细减暗内嵌化
5. 月晕雾洗白纹理 → opacity 0.35→0.16
6. 撕裂太浅 → 深度2.8→3.4+撕裂缘更参差
7. 碎石贴月 → 拖带拉宽±48/向外3-18
8. 银河不可见 → skybox转向1.35/0.3
9. CTA文字被亮月面淹没 → 相机24→26.5+文字暗底

工具: 新增node静态服务器(替代僵死的python)+shoot.js截图工作流
This commit is contained in:
leefer
2026-08-02 13:55:31 +08:00
parent d5d4623aa9
commit a7a425375b
2 changed files with 36 additions and 19 deletions
+16
View File
@@ -305,6 +305,22 @@ html, body {
.error-code-line .ec-val { color: var(--code-green); }
.error-code-line .ec-err { color: var(--red); }
/* === CTA文字暗底(亮月面背景下的可读性) === */
.cta-content h2, .cta-content p {
text-shadow: 0 2px 18px rgba(2, 4, 8, 0.9), 0 0 40px rgba(2, 4, 8, 0.6);
}
.cta-content {
position: relative;
}
.cta-content::before {
content: "";
position: absolute;
inset: -60px -40px;
background: radial-gradient(ellipse at center, rgba(2, 4, 8, 0.55), transparent 70%);
z-index: -1;
pointer-events: none;
}
/* === Hero 右侧留白给月亮 === */
@media (min-width: 900px) {
.space-hero-content { margin-left: 6vw; }
+20 -19
View File
@@ -35,6 +35,7 @@ if (!window.SPACE_MODE) {
工具
============================================================ */
function glowTexture(inner, mid, size) {
size = size || 256;
var c = document.createElement("canvas");
c.width = c.height = size;
var x = c.getContext("2d");
@@ -106,8 +107,8 @@ if (!window.SPACE_MODE) {
var mat = new THREE.MeshBasicMaterial({ map: tex, side: THREE.BackSide, depthWrite: false });
mat.fog = false;
skyMesh = new THREE.Mesh(new THREE.SphereGeometry(1200, 48, 32), mat);
skyMesh.rotation.y = 2.2; // 让银河带处于好看的方位
skyMesh.rotation.z = 0.12;
skyMesh.rotation.y = 1.35; // 让银河带横贯可见半球
skyMesh.rotation.x = 0.3;
scene.add(skyMesh);
loadState.sky = true;
}, undefined, function () { loadState.sky = true; });
@@ -175,9 +176,9 @@ if (!window.SPACE_MODE) {
var moonGroup = new THREE.Group();
var MOON_R = 10;
var moonMat = new THREE.MeshStandardMaterial({
color: 0xbfc3c9, // 冷调青灰
color: 0xc9ccd2, // 冷调青灰(提亮度,纹理可见)
roughness: 0.98, metalness: 0.0,
bumpScale: 0.6
bumpScale: 0.9 // 更强环形山起伏
});
var moon = null;
@@ -227,7 +228,7 @@ if (!window.SPACE_MODE) {
py += Math.sin(ang) * (len * W / steps) * 0.55;
pts.push([px, py]);
}
[[7, "rgba(70,220,170,0.1)"], [3.5, "rgba(100,240,190,0.22)"], [1.4, "rgba(200,255,235,0.9)"]].forEach(function (ps) {
[[4, "rgba(70,220,170,0.06)"], [2, "rgba(100,240,190,0.12)"], [0.9, "rgba(200,255,235,0.75)"]].forEach(function (ps) {
x.strokeStyle = ps[1]; x.lineWidth = ps[0];
x.beginPath(); x.moveTo(pts[0][0], pts[0][1]);
for (var k = 1; k < pts.length; k++) x.lineTo(pts[k][0], pts[k][1]);
@@ -250,8 +251,8 @@ if (!window.SPACE_MODE) {
var n = 0.5 + 0.5 * Math.sin(v.x * 13.1) * Math.sin(v.y * 9.7) * Math.sin(v.z * 11.3)
+ 0.25 * Math.sin(v.x * 31.7 + v.y * 23.9);
n = Math.max(0, Math.min(1, n));
var depth = fall * (0.4 + 2.8 * n * (0.35 + 0.65 * fall));
if (ang > 0.3) depth += (Math.random() - 0.5) * 0.4; // 撕裂缘参差
var depth = fall * (0.5 + 3.4 * n * (0.35 + 0.65 * fall));
if (ang > 0.28) depth += (Math.random() - 0.5) * 0.55; // 撕裂缘参差
var newR = MOON_R - Math.max(0, depth);
pos.setXYZ(i, v.x * newR, v.y * newR, v.z * newR);
}
@@ -292,12 +293,12 @@ if (!window.SPACE_MODE) {
loadState.moon = true;
}, undefined, function () { loadState.moon = true; });
// 月缘柔光(青灰)
// 月缘柔光(青灰,克制——别洗白纹理)
var moonHalo = new THREE.Sprite(new THREE.SpriteMaterial({
map: glowTexture("rgba(175,200,195,0.5)", "rgba(160,190,185,0.4)"),
transparent: true, opacity: 0.35, blending: THREE.AdditiveBlending, depthWrite: false
transparent: true, opacity: 0.16, blending: THREE.AdditiveBlending, depthWrite: false
}));
moonHalo.scale.set(30, 30, 1);
moonHalo.scale.set(26, 26, 1);
moonGroup.add(moonHalo);
// 伤口溢出辉光(活着的事件)
@@ -349,8 +350,8 @@ if (!window.SPACE_MODE) {
var bitan = new THREE.Vector3().crossVectors(woundDirLocal, tangent).normalize();
var dummy = new THREE.Object3D();
for (var d = 0; d < DEBRIS_N; d++) {
var along = (Math.random() - 0.3) * 30; // 沿切线拖带
var out = 1.5 + Math.random() * 9; // 向外飞散距离
var along = (Math.random() - 0.3) * 48; // 沿切线拖带(更宽)
var out = 3 + Math.random() * 15; // 向外飞散距离(不贴月)
var pos = woundPoint.clone()
.add(tangent.clone().multiplyScalar(along))
.add(woundDirLocal.clone().multiplyScalar(out))
@@ -445,14 +446,14 @@ if (!window.SPACE_MODE) {
});
}
/* ---------- 光照(太阳为唯一主光源) ---------- */
var sunLight = new THREE.DirectionalLight(0xffdcae, 2.6);
sunLight.position.set(-150, 70, -260);
/* ---------- 光照(前左上方主光: 月面左亮右暗,环形山显形) ---------- */
var sunLight = new THREE.DirectionalLight(0xffe3c0, 2.8);
sunLight.position.set(-114, 71, 118); // 前左上,照亮相机可见半球的左侧
scene.add(sunLight);
var fillCold = new THREE.DirectionalLight(0x5a6fc8, 0.4); // 背光面冷蓝紫
fillCold.position.set(120, -40, 120);
var fillCold = new THREE.DirectionalLight(0x5a6fc8, 0.55); // 右前方冷补光,碎石不死黑
fillCold.position.set(120, -30, 100);
scene.add(fillCold);
scene.add(new THREE.AmbientLight(0x2a3452, 0.55));
scene.add(new THREE.AmbientLight(0x2a3452, 0.6));
var rimLight = new THREE.DirectionalLight(0x8899ff, 0.35);
rimLight.position.set(80, -40, 60);
scene.add(rimLight);
@@ -534,7 +535,7 @@ if (!window.SPACE_MODE) {
camera.position.z = lerp(220, isJourney ? 46 : 42, w);
if (skyMesh) skyMesh.rotation.y += 0.004 * (1 - warpT);
} else if (isJourney) {
camera.position.z = lerp(46, 24, ep);
camera.position.z = lerp(46, 26.5, ep);
camera.position.y = lerp(0, 3, ep);
} else {
camera.position.z = 42;