98 lines
4.9 KiB
JavaScript
98 lines
4.9 KiB
JavaScript
/**
|
||
* 智能体头像批量生成(DiceBear bottts 机器人风)
|
||
* 从资源库 js/data/sources/dicebear-bottts.js 读取风格定义,
|
||
* 用确定性 seed 生成 10 套头像 SVG,输出到 output/agent-avatars/,
|
||
* 同时生成 preview.html 便于浏览器预览。
|
||
*
|
||
* 用法:node scripts/gen-agent-avatars.js
|
||
*/
|
||
'use strict';
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const vm = require('vm');
|
||
|
||
const ROOT = path.resolve(__dirname, '..');
|
||
const OUT_DIR = path.join(ROOT, 'output', 'agent-avatars');
|
||
|
||
// —— 模拟浏览器全局:DiceBear 风格文件写入 window.HGB_Dicebear_* ——
|
||
global.window = global;
|
||
|
||
// 1) 加载 29 种 DiceBear 风格定义中的 bottts(机器人)
|
||
const styleFile = path.join(ROOT, 'js', 'data', 'sources', 'dicebear-bottts.js');
|
||
const styleSrc = fs.readFileSync(styleFile, 'utf8');
|
||
vm.runInThisContext(styleSrc, { filename: styleFile }); // 定义 window.HGB_Dicebear_bottts
|
||
|
||
// 2) 加载 DiceBear 渲染引擎(const 声明经 vm 进入全局词法绑定,与 scripts/avatar-ai-smoke.js 一致)
|
||
const engineSrc = fs.readFileSync(path.join(ROOT, 'js', 'core', 'dicebear.js'), 'utf8');
|
||
vm.runInThisContext(engineSrc, { filename: 'js/core/dicebear.js' }); // 定义 HGB_Dicebear
|
||
|
||
// 3) 从资源库 tabler 源提取「房子属性」图标(smart-home 智能家居)用于叠加徽章
|
||
const tablerFile = path.join(ROOT, 'js', 'data', 'sources', 'tabler.js');
|
||
vm.runInThisContext(fs.readFileSync(tablerFile, 'utf8'), { filename: 'tabler.js' }); // 定义 window.HGB_Source_tabler
|
||
const tablerIcons = window['HGB_Source_tabler'].icons;
|
||
const houseIcon = tablerIcons.find(x => x.id === 'tabler:smart-home') || tablerIcons.find(x => x.id === 'tabler:home');
|
||
if (!houseIcon) { console.error('❌ 资源库未找到 smart-home/home 图标'); process.exit(1); }
|
||
const houseBody = houseIcon.svg; // 形如 <path .../><path .../>(tabler 为 stroke 风格)
|
||
|
||
// 徽章:圆形底 + 房子图标,右下角 (140,140),整体在 180 viewBox 圆形裁切内
|
||
const BADGE_CX = 140, BADGE_CY = 140, BADGE_R = 22, ICON_SIZE = 24, ICON_SCALE = 0.85;
|
||
const houseBadge = `<g transform="translate(${BADGE_CX} ${BADGE_CY})"><circle r="${BADGE_R}" fill="#5561d4"/><g transform="translate(${-ICON_SIZE / 2} ${-ICON_SIZE / 2}) scale(${ICON_SCALE})" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${houseBody}</g></g>`;
|
||
|
||
// 4) 生成 10 套:seed 用固定前缀 + 序号,保证可复现
|
||
const COUNT = 10;
|
||
const SEED_BASE = 'agent';
|
||
const seeds = [];
|
||
for (let i = 1; i <= COUNT; i++) seeds.push(SEED_BASE + '-' + i);
|
||
|
||
const cards = [];
|
||
for (let i = 0; i < seeds.length; i++) {
|
||
const { svg } = HGB_Dicebear.renderAvatar('bottts', seeds[i]);
|
||
// 叠加房子属性徽章(插到 </svg> 前)
|
||
const enriched = svg.replace(/<\/svg>$/, houseBadge + '</svg>');
|
||
const file = 'agent-' + String(i + 1).padStart(2, '0') + '.svg';
|
||
cards.push({ file, seed: seeds[i], svg: enriched });
|
||
}
|
||
|
||
// 4) 写文件
|
||
fs.mkdirSync(OUT_DIR, { recursive: true });
|
||
for (const c of cards) {
|
||
fs.writeFileSync(path.join(OUT_DIR, c.file), c.svg, 'utf8');
|
||
console.log('✅ ' + c.file + ' seed=' + c.seed);
|
||
}
|
||
|
||
// 5) 预览页(内联全部 SVG,浏览器直接查看)
|
||
const preview = `<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>智能体头像 · 10 套预览(DiceBear bottts · 房子属性)</title>
|
||
<style>
|
||
body { font-family: -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif; background:#0f1115; color:#e8eaed; margin:0; padding:32px; }
|
||
h1 { font-size:20px; margin:0 0 4px; }
|
||
.sub { color:#9aa0a6; font-size:13px; margin-bottom:24px; }
|
||
.grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(140px,1fr)); gap:16px; max-width:1000px; }
|
||
.card { background:#1b1e26; border:1px solid #2a2f3a; border-radius:12px; padding:16px; text-align:center; }
|
||
.card svg { width:96px; height:96px; border-radius:50%; background:#fff; }
|
||
.card .name { margin-top:10px; font-size:12px; color:#bdc1c6; }
|
||
.card .seed { font-size:11px; color:#80868b; }
|
||
a.dl { display:inline-block; margin-top:6px; font-size:11px; color:#8ab4f8; text-decoration:none; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<h1>🤖 智能体头像 · 10 套(带房子属性)</h1>
|
||
<div class="sub">DiceBear bottts(机器人)风格 + 房子属性徽章(资源库 tabler · smart-home)· 确定性 seed 生成</div>
|
||
<div class="grid">
|
||
${cards.map(c => `<div class="card">
|
||
${c.svg}
|
||
<div class="name">智能体 ${c.file.replace('.svg', '')}</div>
|
||
<div class="seed">seed: ${c.seed}</div>
|
||
<a class="dl" href="${c.file}" download>下载 SVG</a>
|
||
</div>`).join('\n')}
|
||
</div>
|
||
</body>
|
||
</html>`;
|
||
fs.writeFileSync(path.join(OUT_DIR, 'preview.html'), preview, 'utf8');
|
||
console.log('\n🎉 已生成 ' + cards.length + ' 套头像 → output/agent-avatars/');
|
||
console.log('预览:打开 output/agent-avatars/preview.html');
|