// 用 sharp 把 SVG 转为多尺寸 PNG import sharp from 'sharp'; import { readFile, writeFile } from 'node:fs/promises'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const svg = await readFile(path.join(__dirname, '../public/pwa-icon.svg')); const targets = [ // 标准 PWA icons { out: 'public/pwa/pwa-192x192.png', size: 192, type: 'normal' }, { out: 'public/pwa/pwa-512x512.png', size: 512, type: 'normal' }, // maskable:四周留 20% 安全区,logo 居中缩到 60% { out: 'public/pwa/pwa-maskable-512x512.png', size: 512, type: 'maskable' }, // apple touch { out: 'public/pwa/apple-touch-icon.png', size: 180, type: 'normal' }, // favicon { out: 'public/favicon-32x32.png', size: 32, type: 'normal' }, { out: 'public/favicon-16x16.png', size: 16, type: 'normal' }, ]; const bgColor = { r: 27, g: 110, b: 243 }; // 渐变起始色 #1B6EF3 for (const { out, size, type } of targets) { let buffer = await sharp(svg).resize(size, size).png().toBuffer(); if (type === 'maskable') { // maskable 重新画:蓝底全填 + logo 60% const inner = await sharp(svg).resize(Math.floor(size * 0.6), Math.floor(size * 0.6)).png().toBuffer(); buffer = await sharp({ create: { width: size, height: size, channels: 4, background: bgColor }, }) .composite([{ input: inner, gravity: 'center' }]) .png() .toBuffer(); } await writeFile(path.join(__dirname, '..', out), buffer); console.log('✓', out, `${size}x${size}`, type); } console.log('Done.');