gen-tabbar-icons.mjs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. /**
  2. * 生成 81×81 TabBar PNG 图标(透明底,适合微信小程序)
  3. * 用法:node scripts/gen-tabbar-icons.mjs
  4. */
  5. import fs from 'node:fs'
  6. import path from 'node:path'
  7. import { fileURLToPath } from 'node:url'
  8. import sharp from 'sharp'
  9. const __dirname = path.dirname(fileURLToPath(import.meta.url))
  10. const outDir = path.resolve(__dirname, '../src/static/tabbar')
  11. const GRAY = '#8C7B6A'
  12. const ORANGE = '#FF6B35'
  13. function svgIcon(type, color) {
  14. if (type === 'home') {
  15. return `<svg width="81" height="81" xmlns="http://www.w3.org/2000/svg">
  16. <path d="M40.5 18 L62 34 V62 H52 V44 H29 V62 H19 V34 Z" fill="none" stroke="${color}" stroke-width="4" stroke-linejoin="round"/>
  17. </svg>`
  18. }
  19. if (type === 'scan') {
  20. return `<svg width="81" height="81" xmlns="http://www.w3.org/2000/svg">
  21. <rect x="18" y="18" width="45" height="45" rx="6" fill="none" stroke="${color}" stroke-width="4"/>
  22. <rect x="24" y="24" width="10" height="10" fill="${color}"/>
  23. <rect x="47" y="24" width="10" height="10" fill="${color}"/>
  24. <rect x="24" y="47" width="10" height="10" fill="${color}"/>
  25. <rect x="41" y="41" width="8" height="8" fill="${color}"/>
  26. <rect x="47" y="47" width="10" height="10" fill="${color}"/>
  27. </svg>`
  28. }
  29. if (type === 'coupon') {
  30. return `<svg width="81" height="81" xmlns="http://www.w3.org/2000/svg">
  31. <rect x="16" y="24" width="49" height="33" rx="6" fill="none" stroke="${color}" stroke-width="4"/>
  32. <circle cx="16" cy="40.5" r="5" fill="#FFF9F3" stroke="${color}" stroke-width="3"/>
  33. <circle cx="65" cy="40.5" r="5" fill="#FFF9F3" stroke="${color}" stroke-width="3"/>
  34. <line x1="28" y1="40" x2="53" y2="40" stroke="${color}" stroke-width="3" stroke-linecap="round"/>
  35. </svg>`
  36. }
  37. return `<svg width="81" height="81" xmlns="http://www.w3.org/2000/svg">
  38. <circle cx="40.5" cy="32" r="12" fill="none" stroke="${color}" stroke-width="4"/>
  39. <path d="M20 62 C20 50 58 50 61 62" fill="none" stroke="${color}" stroke-width="4" stroke-linecap="round"/>
  40. </svg>`
  41. }
  42. async function writeIcon(name, type, color) {
  43. const svg = svgIcon(type, color)
  44. const buf = await sharp(Buffer.from(svg)).png().toBuffer()
  45. fs.writeFileSync(path.join(outDir, name), buf)
  46. }
  47. async function main() {
  48. fs.mkdirSync(outDir, { recursive: true })
  49. const items = [
  50. ['home.png', 'home', GRAY],
  51. ['home-active.png', 'home', ORANGE],
  52. ['scan.png', 'scan', GRAY],
  53. ['scan-active.png', 'scan', ORANGE],
  54. ['coupon.png', 'coupon', GRAY],
  55. ['coupon-active.png', 'coupon', ORANGE],
  56. ['profile.png', 'profile', GRAY],
  57. ['profile-active.png', 'profile', ORANGE]
  58. ]
  59. for (const [file, type, color] of items) {
  60. await writeIcon(file, type, color)
  61. console.log('wrote', file)
  62. }
  63. }
  64. main().catch(err => {
  65. console.error(err)
  66. process.exit(1)
  67. })