feat: 初始化画个标仓库 - AI驱动设计系统(BYOK模式) - 224源/371504图标+25海报源+130技能
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* 画个标 · 海报生成引擎:版式模板 + 配色 + 元素构造
|
||||
* 决策(paletteId/layoutId/title/sub/icon)→ 元素数组,供 renderer 渲染。
|
||||
*/
|
||||
const HGB_PosterGenerator = (function () {
|
||||
'use strict';
|
||||
|
||||
const PALETTES = [
|
||||
{ id: 'indigo', name: '靛蓝', bg: '#1e1b4b', primary: '#ffffff', accent: '#f59e0b' },
|
||||
{ id: 'crimson', name: '深红', bg: '#7f1d1d', primary: '#ffffff', accent: '#fbbf24' },
|
||||
{ id: 'ocean', name: '海洋', bg: '#0c4a6e', primary: '#ffffff', accent: '#38bdf8' },
|
||||
{ id: 'forest', name: '森林', bg: '#14532d', primary: '#ffffff', accent: '#86efac' },
|
||||
{ id: 'minimal', name: '极简', bg: '#ffffff', primary: '#111827', accent: '#4f46e5' }
|
||||
];
|
||||
|
||||
function uid(p) { return p + '_' + Date.now().toString(36) + Math.random().toString(36).slice(2, 6); }
|
||||
|
||||
function rect(id, x, y, w, h, fill) { return { id, type: 'rect', x, y, w, h, fill }; }
|
||||
function circle(id, cx, cy, r, fill) { return { id, type: 'circle', cx, cy, r, fill }; }
|
||||
function text(id, text, x, y, fontSize, fontWeight, fill, align) {
|
||||
return { id, type: 'text', text, x, y, fontSize, fontWeight, fill, align: align || 'start' };
|
||||
}
|
||||
|
||||
const LAYOUTS = [
|
||||
{
|
||||
id: 'centered', name: '居中对称', emoji: '🎯',
|
||||
build(spec, o) {
|
||||
const cw = spec.w, ch = spec.h, els = [];
|
||||
els.push(rect(uid('bg'), 0, 0, cw, ch, o.palette.bg));
|
||||
els.push(circle(uid('dot'), cw / 2, ch * 0.30, ch * 0.12, o.palette.accent));
|
||||
const fs = Math.round(cw * 0.075);
|
||||
els.push(text(uid('title'), o.title, cw / 2, ch * 0.50, fs, 800, o.palette.primary, 'middle'));
|
||||
if (o.sub) els.push(text(uid('sub'), o.sub, cw / 2, ch * 0.56, Math.round(fs * 0.38), 400, o.palette.primary, 'middle'));
|
||||
els.push(rect(uid('bar'), cw / 2 - cw * 0.12, ch * 0.62, cw * 0.24, 8, o.palette.accent));
|
||||
return els;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'left', name: '左对齐', emoji: '◀️',
|
||||
build(spec, o) {
|
||||
const cw = spec.w, ch = spec.h, els = [];
|
||||
els.push(rect(uid('bg'), 0, 0, cw, ch, o.palette.bg));
|
||||
els.push(rect(uid('side'), 0, 0, cw * 0.06, ch, o.palette.accent));
|
||||
const mx = cw * 0.13;
|
||||
const fs = Math.round(cw * 0.08);
|
||||
els.push(text(uid('title'), o.title, mx, ch * 0.44, fs, 800, o.palette.primary, 'start'));
|
||||
if (o.sub) els.push(text(uid('sub'), o.sub, mx, ch * 0.52, Math.round(fs * 0.36), 400, o.palette.primary, 'start'));
|
||||
els.push(rect(uid('bar'), mx, ch * 0.58, cw * 0.18, 8, o.palette.accent));
|
||||
return els;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'banner', name: '顶部横幅', emoji: '📢',
|
||||
build(spec, o) {
|
||||
const cw = spec.w, ch = spec.h, els = [];
|
||||
els.push(rect(uid('bg'), 0, 0, cw, ch, o.palette.bg));
|
||||
els.push(rect(uid('band'), 0, ch * 0.18, cw, ch * 0.16, o.palette.accent));
|
||||
const fs = Math.round(cw * 0.07);
|
||||
els.push(text(uid('title'), o.title, cw / 2, ch * 0.26, fs, 800, o.palette.bg, 'middle'));
|
||||
if (o.sub) els.push(text(uid('sub'), o.sub, cw / 2, ch * 0.55, Math.round(fs * 0.42), 400, o.palette.primary, 'middle'));
|
||||
return els;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
/** 决策 → 元素数组 */
|
||||
function generate(spec, decision) {
|
||||
const palette = PALETTES.find(p => p.id === decision.paletteId) || PALETTES[0];
|
||||
const layout = LAYOUTS.find(l => l.id === decision.layoutId) || LAYOUTS[0];
|
||||
const o = { palette, title: decision.title || '海报标题', sub: decision.sub || '' };
|
||||
return layout.build(spec, o);
|
||||
}
|
||||
|
||||
function defaultDecision(title, sub) {
|
||||
return { paletteId: 'indigo', layoutId: 'centered', title: title || '海报标题', sub: sub || '' };
|
||||
}
|
||||
|
||||
return { PALETTES, LAYOUTS, generate, defaultDecision };
|
||||
})();
|
||||
Reference in New Issue
Block a user