generate-icons.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. const { PNG } = require('pngjs');
  2. const fs = require('fs');
  3. const path = require('path');
  4. const SIZE = 81;
  5. const INACTIVE_COLOR = [148, 163, 184]; // #94a3b8
  6. const ACTIVE_COLOR = [16, 185, 129]; // #10b981
  7. // 创建 PNG 图标
  8. function createIcon(draw, color) {
  9. const png = new PNG({ width: SIZE, height: SIZE });
  10. const data = png.data;
  11. // 填充透明背景
  12. for (let y = 0; y < SIZE; y++) {
  13. for (let x = 0; x < SIZE; x++) {
  14. const idx = (SIZE * y + x) << 2;
  15. data[idx] = 0;
  16. data[idx + 1] = 0;
  17. data[idx + 2] = 0;
  18. data[idx + 3] = 0;
  19. }
  20. }
  21. // 绘制图标
  22. draw(png, color);
  23. return PNG.sync.write(png);
  24. }
  25. // 绘制像素
  26. function setPixel(png, x, y, color, alpha = 255) {
  27. const idx = (SIZE * y + x) << 2;
  28. png.data[idx] = color[0];
  29. png.data[idx + 1] = color[1];
  30. png.data[idx + 2] = color[2];
  31. png.data[idx + 3] = alpha;
  32. }
  33. // 绘制圆角矩形
  34. function drawRoundRect(png, x, y, w, h, r, color) {
  35. for (let dy = 0; dy < h; dy++) {
  36. for (let dx = 0; dx < w; dx++) {
  37. const px = x + dx;
  38. const py = y + dy;
  39. // 检查是否在圆角内
  40. let inCorner = false;
  41. if (dx < r && dy < r) {
  42. // 左上角
  43. const dist = Math.sqrt((r - dx - 1) ** 2 + (r - dy - 1) ** 2);
  44. inCorner = dist > r;
  45. } else if (dx >= w - r && dy < r) {
  46. // 右上角
  47. const dist = Math.sqrt((dx - w + r) ** 2 + (r - dy - 1) ** 2);
  48. inCorner = dist > r;
  49. } else if (dx < r && dy >= h - r) {
  50. // 左下角
  51. const dist = Math.sqrt((r - dx - 1) ** 2 + (dy - h + r) ** 2);
  52. inCorner = dist > r;
  53. } else if (dx >= w - r && dy >= h - r) {
  54. // 右下角
  55. const dist = Math.sqrt((dx - w + r) ** 2 + (dy - h + r) ** 2);
  56. inCorner = dist > r;
  57. }
  58. if (!inCorner) {
  59. setPixel(png, px, py, color);
  60. }
  61. }
  62. }
  63. }
  64. // 绘制圆形
  65. function drawCircle(png, cx, cy, r, color) {
  66. for (let y = -r; y <= r; y++) {
  67. for (let x = -r; x <= r; x++) {
  68. if (x * x + y * y <= r * r) {
  69. setPixel(png, cx + x, cy + y, color);
  70. }
  71. }
  72. }
  73. }
  74. // 绘制矩形
  75. function drawRect(png, x, y, w, h, color) {
  76. for (let dy = 0; dy < h; dy++) {
  77. for (let dx = 0; dx < w; dx++) {
  78. setPixel(png, x + dx, y + dy, color);
  79. }
  80. }
  81. }
  82. // 工作台图标 - 网格
  83. function drawWork(png, color) {
  84. const s = 12; // 间距
  85. const b = 16; // 方块大小
  86. const ox = 18; // 偏移
  87. const oy = 18;
  88. drawRoundRect(png, ox, oy, b, b, 3, color);
  89. drawRoundRect(png, ox + b + s, oy, b, b, 3, color);
  90. drawRoundRect(png, ox, oy + b + s, b, b, 3, color);
  91. drawRoundRect(png, ox + b + s, oy + b + s, b, b, 3, color);
  92. }
  93. // 订单图标 - 清单
  94. function drawOrder(png, color) {
  95. const x = 22, y = 16, w = 36, h = 48;
  96. // 外框
  97. drawRoundRect(png, x, y, w, h, 4, color);
  98. // 内部线条(用背景色)
  99. const bgColor = [0, 0, 0];
  100. drawRect(png, x + 8, y + 12, 20, 3, bgColor);
  101. drawRect(png, x + 8, y + 22, 16, 3, bgColor);
  102. drawRect(png, x + 8, y + 32, 18, 3, bgColor);
  103. }
  104. // 设备图标 - 盒子
  105. function drawDevice(png, color) {
  106. const x = 18, y = 22, w = 44, h = 36;
  107. drawRoundRect(png, x, y, w, h, 6, color);
  108. // 屏幕
  109. const bgColor = [0, 0, 0];
  110. drawRoundRect(png, x + 6, y + 6, w - 12, h - 12, 3, bgColor);
  111. // 底座
  112. drawRect(png, x + 16, y + h, 12, 6, color);
  113. drawRect(png, x + 10, y + h + 6, 24, 3, color);
  114. }
  115. // 我的图标 - 人形
  116. function drawMy(png, color) {
  117. // 头部
  118. drawCircle(png, 40, 26, 12, color);
  119. // 身体
  120. drawRoundRect(png, 20, 42, 40, 24, 10, color);
  121. }
  122. // 生成图标
  123. const icons = [
  124. { name: 'work', draw: drawWork },
  125. { name: 'order', draw: drawOrder },
  126. { name: 'device', draw: drawDevice },
  127. { name: 'my', draw: drawMy },
  128. ];
  129. const outputDir = path.join(__dirname, '../src/static/tabbar');
  130. icons.forEach(({ name, draw }) => {
  131. // 普通状态
  132. const inactivePng = createIcon(draw, INACTIVE_COLOR);
  133. fs.writeFileSync(path.join(outputDir, `${name}.png`), inactivePng);
  134. console.log(`Created ${name}.png`);
  135. // 选中状态
  136. const activePng = createIcon(draw, ACTIVE_COLOR);
  137. fs.writeFileSync(path.join(outputDir, `${name}-active.png`), activePng);
  138. console.log(`Created ${name}-active.png`);
  139. });
  140. console.log('All icons generated!');