https://www.multiavatar.com/
利用 aardio 的 WebView 控件和本地的 multiavatar.min.js 算法,打造了一个纯离线、高速、可视化的头像批量生成工具。它能够在几秒内生成 100 张完全不同的 SVG 矢量头像,并且可以一键同步转换为高清 PNG(转换依赖光庆的svgtopng库附件已提供)。

import win.ui;
/*DSG{{*/
mainForm = win.form(text="Multiavatar 纯离线高速生成器";right=458;bottom=339)
mainForm.add(
btnGenerate={cls="button";text="开始生成";left=25;top=25;right=434;bottom=70;z=2};
chkToPng={cls="checkbox";text="同步生成 PNG 格式";left=26;top=293;right=200;bottom=311;z=3;checked=1};
logView={cls="edit";left=26;top=94;right=433;bottom=273;edge=1;multiline=1;readonly=1;vscroll=1;z=1}
);
/*}}*/
import web.view;
import godking.svgtopng;
mainForm.show();
// 1. 读取本地 JS 算法库
var jsPath = io.fullpath("/multiavatar.min.js");
if(!io.exist(jsPath)){
mainForm.logView.print("【错误】未在程序目录下找到 multiavatar.min.js!");
mainForm.logView.print("请将下载的 multiavatar.min.js 放入以下目录:");
mainForm.logView.print(io.fullpath("/"));
win.loopMessage();
return;
}
var jsCode = string.load(jsPath);
if(!jsCode || #jsCode == 0){
mainForm.logView.print("【错误】读取 multiavatar.min.js 失败!");
win.loopMessage();
return;
}
mainForm.logView.print("【成功】已载入本地算法库。");
// 2. 初始化 WebView 并注入 JS
var wb = web.view(mainForm);
var htmlStart = `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>
`;
var htmlEnd = `
function generateAvatar(seed) {
try {
return multiavatar(seed);
} catch(e) {
return "ERROR:" + e.message;
}
}
</script>
</head>
<body></body>
</html>`;
wb.html = htmlStart ++ jsCode ++ htmlEnd;
wb.wait();
// 3. 创建分类目录(download/svg 和 download/png)
var baseDir = io.fullpath("/download/");
var svgDir = io.fullpath("/download/svg/");
var pngDir = io.fullpath("/download/png/");
io.createDir(svgDir);
// pngDir 在需要时才创建(见按钮事件)
// 4. 按钮点击事件
mainForm.btnGenerate.oncommand = function(id, event){
// 防止重复点击
mainForm.btnGenerate.disabled = true;
mainForm.logView.print('\n==============================');
mainForm.logView.print("开始生成 100 张头像...");
var needPng = mainForm.chkToPng.checked;
if(needPng){
io.createDir(pngDir); // 确保 PNG 目录存在
mainForm.logView.print("【模式】SVG + PNG 同步生成");
} else {
mainForm.logView.print("【模式】仅生成 SVG");
}
var startTime = time.tick();
var succCount = 0;
// 异步循环,避免阻塞界面
mainForm.setTimeout(
function(){
for(i=1; 100; 1){
var seed = math.random(100000, 999999) ++ "_" ++ i;
var svgData = wb.xcall("generateAvatar", seed);
if(!svgData || string.startsWith(svgData, "ERROR")){
mainForm.logView.print(string.format("[%d/100] 生成 SVG 失败", i));
win.delay(1);
continue;
}
// 保存 SVG(始终保存)
var svgPath = io.fullpath(svgDir ++ "/avatar_" ++ i ++ ".svg");
string.save(svgPath, svgData);
succCount++;
// 如果勾选了 PNG,则转换
if(needPng){
var pngData = godking.svgtopng(svgPath, 200, 200);
if(pngData){
var pngPath = io.fullpath(pngDir ++ "/avatar_" ++ i ++ ".png");
string.save(pngPath, pngData);
mainForm.logView.print(string.format("[%d/100] ✔ avatar_%d.svg + .png", i, i));
} else {
mainForm.logView.print(string.format("[%d/100] ⚠ PNG 转换失败(SVG 已保存)", i));
}
} else {
mainForm.logView.print(string.format("[%d/100] ✔ avatar_%d.svg", i, i));
}
win.delay(1);
}
var spendTime = (time.tick() - startTime) / 1000;
mainForm.logView.print('\n==================================');
mainForm.logView.print(string.format("全部完成!成功生成 %d 张头像", succCount));
mainForm.logView.print(string.format("耗时:%.2f 秒", spendTime));
mainForm.logView.print("SVG 保存目录:" + svgDir);
if(needPng) mainForm.logView.print("PNG 保存目录:" + pngDir);
mainForm.logView.print("==================================");
mainForm.btnGenerate.disabled = false; // 恢复按钮
}, 500
);
}
win.loopMessage();