/** * 🏠 emoji 头像 PNG 批量生成 * 从资源库 twemoji 源提取 house 表情彩色 SVG, * 生成 10 个渐变背景圆形头像(1024×1024),用 Chrome headless 导出 PNG。 * * 用法:node scripts/gen-emoji-avatars-png.js */ 'use strict'; const fs = require('fs'); const path = require('path'); const vm = require('vm'); const { execFileSync } = require('child_process'); const ROOT = path.resolve(__dirname, '..'); const OUT_DIR = path.join(ROOT, 'output', 'agent-avatars-png'); const TMP_DIR = path.join(ROOT, 'output', '.tmp-emoji'); const CHROME = 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe'; // —— 1. 从资源库读取 twemoji 源,提取 house(🏠)彩色 SVG —— global.window = global; vm.runInThisContext(fs.readFileSync(path.join(ROOT, 'js', 'data', 'sources', 'twemoji.js'), 'utf8'), { filename: 'twemoji.js' }); const icons = window['HGB_Source_twemoji'].icons; const house = icons.find(x => x.id === 'twemoji:house'); if (!house) { console.error('❌ 资源库未找到 twemoji:house'); process.exit(1); } const houseBody = house.svg; // 24 坐标系的 g 内容(含 translate(0 0) scale(0.666…)) // —— 2. 10 个渐变背景(16 进制)—— const BG = [ { from: '#667eea', to: '#764ba2' }, // 蓝紫 { from: '#2193b0', to: '#6dd5ed' }, // 青蓝 { from: '#11998e', to: '#38ef7d' }, // 绿 { from: '#f7971e', to: '#ffd200' }, // 橙黄 { from: '#ee9ca7', to: '#ffdde1' }, // 粉 { from: '#cb2d3e', to: '#ef473a' }, // 红 { from: '#41295a', to: '#2F0743' }, // 紫黑 { from: '#1e3c72', to: '#2a5298' }, // 深蓝 { from: '#f953c6', to: '#b91d73' }, // 玫红 { from: '#0575e6', to: '#021B79' } // 靛蓝 ]; // —— 3. 生成 HTML:1024×1024 圆形渐变底 + 🏠 居中(emoji 内容按 24 坐标缩放 22 → 528px)—— function buildHtml(from, to) { return ` ${houseBody} `; } // —— 4. 逐张导出 PNG —— fs.mkdirSync(OUT_DIR, { recursive: true }); fs.mkdirSync(TMP_DIR, { recursive: true }); for (let i = 0; i < BG.length; i++) { const idx = String(i + 1).padStart(2, '0'); const htmlFile = path.join(TMP_DIR, `avatar-${idx}.html`); const pngFile = path.join(OUT_DIR, `agent-${idx}.png`); fs.writeFileSync(htmlFile, buildHtml(BG[i].from, BG[i].to), 'utf8'); try { execFileSync(CHROME, [ '--headless=new', '--disable-gpu', '--hide-scrollbars', '--force-device-scale-factor=1', '--default-background-color=00000000', '--window-size=1024,1024', '--virtual-time-budget=1000', `--screenshot=${pngFile}`, 'file:///' + htmlFile.replace(/\\/g, '/') ], { stdio: 'pipe' }); console.log(`✅ agent-${idx}.png ${BG[i].from} → ${BG[i].to}`); } catch (e) { console.error(`❌ agent-${idx}.png 失败:`, e.message.split('\n')[0]); } } // 清理临时 HTML fs.rmSync(TMP_DIR, { recursive: true, force: true }); console.log('\n🎉 完成 → output/agent-avatars-png/');