feat: refresh creation config and visual assets
This commit is contained in:
183
scripts/generate-taonier-squish-logo-variants.mjs
Normal file
183
scripts/generate-taonier-squish-logo-variants.mjs
Normal file
@@ -0,0 +1,183 @@
|
||||
import { mkdirSync, writeFileSync } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
const repoRoot = process.cwd();
|
||||
const outputDir = path.join(
|
||||
repoRoot,
|
||||
'public',
|
||||
'branding',
|
||||
'taonier-logo-squish-variants',
|
||||
);
|
||||
|
||||
const variants = [
|
||||
{
|
||||
id: 'taonier-squish-berry-mint',
|
||||
title: '莓果薄荷',
|
||||
topStart: '#ff4778',
|
||||
topEnd: '#ff6b5f',
|
||||
bottomStart: '#12c9b7',
|
||||
bottomEnd: '#16b899',
|
||||
starStart: '#ffd54c',
|
||||
starEnd: '#ffb82e',
|
||||
accent: '#ffc545',
|
||||
background: '#fffaf2',
|
||||
},
|
||||
{
|
||||
id: 'taonier-squish-candy-pop',
|
||||
title: '糖果桃青',
|
||||
topStart: '#ff5fa2',
|
||||
topEnd: '#ff8670',
|
||||
bottomStart: '#2ed7c5',
|
||||
bottomEnd: '#65d8f4',
|
||||
starStart: '#ffe06f',
|
||||
starEnd: '#ffbf4d',
|
||||
accent: '#ffce5e',
|
||||
background: '#fff8fb',
|
||||
},
|
||||
{
|
||||
id: 'taonier-squish-jelly-cream',
|
||||
title: '奶油果冻',
|
||||
topStart: '#ff758d',
|
||||
topEnd: '#ff9a70',
|
||||
bottomStart: '#42d6b5',
|
||||
bottomEnd: '#7ce3c5',
|
||||
starStart: '#fff07a',
|
||||
starEnd: '#ffc955',
|
||||
accent: '#ffd76a',
|
||||
background: '#fffdf4',
|
||||
},
|
||||
{
|
||||
id: 'taonier-squish-bubble-bright',
|
||||
title: '亮彩泡泡',
|
||||
topStart: '#ff3f8f',
|
||||
topEnd: '#ff6d6d',
|
||||
bottomStart: '#00c2b8',
|
||||
bottomEnd: '#00d69a',
|
||||
starStart: '#fff15c',
|
||||
starEnd: '#ffbe35',
|
||||
accent: '#ffbd3c',
|
||||
background: '#fdfcff',
|
||||
},
|
||||
{
|
||||
id: 'taonier-squish-sunny-coral',
|
||||
title: '暖日珊瑚',
|
||||
topStart: '#ff684f',
|
||||
topEnd: '#ff8d67',
|
||||
bottomStart: '#22c4a8',
|
||||
bottomEnd: '#4dd9b5',
|
||||
starStart: '#ffe36d',
|
||||
starEnd: '#ffb948',
|
||||
accent: '#ffc04a',
|
||||
background: '#fff8ed',
|
||||
},
|
||||
{
|
||||
id: 'taonier-squish-neon-cute',
|
||||
title: '霓虹可爱',
|
||||
topStart: '#ff3d7f',
|
||||
topEnd: '#ff4fb8',
|
||||
bottomStart: '#00bfae',
|
||||
bottomEnd: '#00d2ff',
|
||||
starStart: '#fff16a',
|
||||
starEnd: '#ffd13d',
|
||||
accent: '#ffcf45',
|
||||
background: '#fbfbff',
|
||||
},
|
||||
];
|
||||
|
||||
function buildLogoSvg(variant, includeLabel = false) {
|
||||
const labelHeight = includeLabel ? 72 : 0;
|
||||
const height = 1024 + labelHeight;
|
||||
const labelMarkup = includeLabel
|
||||
? `
|
||||
<rect x="0" y="1024" width="1024" height="72" fill="#fffdf8"/>
|
||||
<text x="512" y="1069" text-anchor="middle" font-family="Microsoft YaHei, PingFang SC, Arial, sans-serif" font-size="36" fill="#302a25">${variant.title}</text>`
|
||||
: '';
|
||||
|
||||
return `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="1024" height="${height}" viewBox="0 0 1024 ${height}" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="top" x1="250" y1="180" x2="770" y2="420" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="${variant.topStart}"/>
|
||||
<stop offset="1" stop-color="${variant.topEnd}"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="bottom" x1="250" y1="620" x2="760" y2="850" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="${variant.bottomStart}"/>
|
||||
<stop offset="1" stop-color="${variant.bottomEnd}"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="star" x1="438" y1="452" x2="586" y2="590" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="${variant.starStart}"/>
|
||||
<stop offset="1" stop-color="${variant.starEnd}"/>
|
||||
</linearGradient>
|
||||
<filter id="softShadow" x="140" y="120" width="760" height="790" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feDropShadow dx="0" dy="18" stdDeviation="16" flood-color="#231f20" flood-opacity="0.08"/>
|
||||
</filter>
|
||||
</defs>
|
||||
<rect width="1024" height="${height}" fill="${variant.background}"/>
|
||||
<g filter="url(#softShadow)">
|
||||
<path d="M257.5 295.6C286.4 210.6 398.9 164 513.4 176.9C618.3 188.7 731.3 244.8 776.2 326.4C810.8 389.2 779.6 447.5 709.4 458.8C646.8 468.8 596.8 438.6 543.5 429.4C475.6 417.7 428.6 456.8 370.4 471.7C301.2 489.4 229.3 378.4 257.5 295.6Z" fill="url(#top)"/>
|
||||
<path d="M251.2 672.8C273.2 589.1 366.4 562.5 427.4 617.9C469.5 656.1 503.6 712.6 565.5 721.3C621.9 729.2 660.5 692.6 712.6 673.7C776.6 650.4 839.4 693.4 821.8 762.9C798.2 856 672.2 910 543.4 889.5C424.4 870.6 328.6 812.7 275.9 743.4C259.1 721.4 244.5 698.4 251.2 672.8Z" fill="url(#bottom)"/>
|
||||
</g>
|
||||
<path d="M512 428C528.1 481.8 550.2 503.9 604 520C550.2 536.1 528.1 558.2 512 612C495.9 558.2 473.8 536.1 420 520C473.8 503.9 495.9 481.8 512 428Z" fill="url(#star)"/>
|
||||
<path d="M396 489C405.9 498.8 417.4 503.7 431 504C417.4 504.3 405.9 509.2 396 519C386.1 509.2 374.6 504.3 361 504C374.6 503.7 386.1 498.8 396 489Z" fill="${variant.accent}" opacity="0.95"/>
|
||||
<path d="M630 486C639.9 495.8 651.4 500.7 665 501C651.4 501.3 639.9 506.2 630 516C620.1 506.2 608.6 501.3 595 501C608.6 500.7 620.1 495.8 630 486Z" fill="${variant.accent}" opacity="0.95"/>
|
||||
<circle cx="373" cy="557" r="11" fill="${variant.accent}" opacity="0.88"/>
|
||||
<circle cx="650" cy="555" r="11" fill="${variant.accent}" opacity="0.88"/>
|
||||
${labelMarkup}
|
||||
</svg>`;
|
||||
}
|
||||
|
||||
function buildContactSheetSvg() {
|
||||
const cell = 320;
|
||||
const label = 64;
|
||||
const gap = 28;
|
||||
const width = cell * 3 + gap * 4;
|
||||
const height = (cell + label) * 2 + gap * 3;
|
||||
const items = variants
|
||||
.map((variant, index) => {
|
||||
const row = Math.floor(index / 3);
|
||||
const col = index % 3;
|
||||
const x = gap + col * (cell + gap);
|
||||
const y = gap + row * (cell + label + gap);
|
||||
const logo = buildLogoSvg(variant)
|
||||
.replace(/<\?xml[^>]+>\n/u, '')
|
||||
.replace('<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">', `<svg x="${x}" y="${y}" width="${cell}" height="${cell}" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">`);
|
||||
return `${logo}
|
||||
<rect x="${x}" y="${y + cell}" width="${cell}" height="${label}" fill="#fffdf8"/>
|
||||
<text x="${x + cell / 2}" y="${y + cell + 40}" text-anchor="middle" font-family="Microsoft YaHei, PingFang SC, Arial, sans-serif" font-size="22" fill="#302a25">${String(index + 1).padStart(2, '0')} ${variant.title}</text>`;
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
return `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="${width}" height="${height}" fill="#f6f2eb"/>
|
||||
${items}
|
||||
</svg>`;
|
||||
}
|
||||
|
||||
mkdirSync(outputDir, { recursive: true });
|
||||
|
||||
for (const variant of variants) {
|
||||
writeFileSync(
|
||||
path.join(outputDir, `${variant.id}.svg`),
|
||||
buildLogoSvg(variant),
|
||||
'utf8',
|
||||
);
|
||||
}
|
||||
|
||||
writeFileSync(
|
||||
path.join(outputDir, 'taonier-squish-variants-contact-sheet.svg'),
|
||||
buildContactSheetSvg(),
|
||||
'utf8',
|
||||
);
|
||||
|
||||
console.log(
|
||||
JSON.stringify(
|
||||
{
|
||||
ok: true,
|
||||
outputDir,
|
||||
files: [...variants.map((variant) => `${variant.id}.svg`), 'taonier-squish-variants-contact-sheet.svg'],
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
Reference in New Issue
Block a user