// 对拍矩阵:每套壁纸 × 每种分辨率 各出两张 PNG —— 正常渲染 + 藏起 canvas 的"只有背景"参考帧, // 然后给出"spine 层占了多少像素"的数值。 // 用法:node tools/capture.mjs [--presets xilian,kv37] [--sizes 3440x1440,1920x1080,1080x1920] // [--base http://127.0.0.1:8181] [--propsAt load|dom] [--no-ref] import { spawn } from "node:child_process"; import { mkdir } from "node:fs/promises"; import { resolve } from "node:path"; const argv = process.argv.slice(2); const tag = argv[0]; if (!tag || tag.startsWith("--")) { console.error("usage: node tools/capture.mjs [--presets a,b] [--sizes WxH,...] [--base url] [--propsAt dom] [--no-ref]"); process.exit(2); } const flag = (name, dflt) => { const i = argv.indexOf(`--${name}`); return i >= 0 ? argv[i + 1] : dflt; }; const presets = flag("presets", "xilian,kv37").split(",").filter(Boolean); const sizes = flag("sizes", "3440x1440,1920x1080,1080x1920").split(",").filter(Boolean); const base = flag("base", "http://127.0.0.1:8181"); const propsAt = flag("propsAt", "load"); const wantRef = !argv.includes("--no-ref"); const wait = flag("wait", "25000"); const outDir = resolve("tools/shots", tag); await mkdir(outDir, { recursive: true }); function run(cmd, args) { return new Promise((resolve) => { const p = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"] }); let out = ""; p.stdout.on("data", (d) => (out += d)); p.stderr.on("data", (d) => (out += d)); p.on("close", (code) => resolve({ code, out })); }); } const url = (extra) => `${base}/index.html?${extra}`; const props = (preset) => `__props=${encodeURIComponent(JSON.stringify({ preset }))}`; const rows = []; for (const preset of presets) { for (const size of sizes) { const [w, h] = size.split("x"); const main = resolve(outDir, `${preset}-${size}.png`); const q = `${props(preset)}&__freeze=1${propsAt === "dom" ? "&__propsAt=dom" : ""}`; const a = await run(process.execPath, ["tools/shot.mjs", main, url(q), w, h, wait]); if (a.code !== 0) { console.log(`FAIL ${preset} ${size}: ${a.out.trim().split("\n").pop()}`); continue; } let refLine = ""; if (wantRef) { const ref = resolve(outDir, `${preset}-${size}.ref.png`); const b = await run(process.execPath, ["tools/shot.mjs", ref, url(q + "&__hide=canvas"), w, h, wait]); if (b.code === 0) { const d = await run(process.execPath, ["tools/diff.mjs", ref, main]); refLine = d.out.trim(); } else { refLine = "ref FAILED"; } } rows.push(`${preset.padEnd(7)} ${size.padEnd(11)} spine 层贡献: ${refLine}`); console.log(rows[rows.length - 1]); } } console.log(`\n输出目录: tools/shots/${tag}/`);