const { PNG } = require('pngjs'); const fs = require('fs'); const path = require('path'); const SIZE = 81; const INACTIVE_COLOR = [148, 163, 184]; // #94a3b8 const ACTIVE_COLOR = [16, 185, 129]; // #10b981 // 创建 PNG 图标 function createIcon(draw, color) { const png = new PNG({ width: SIZE, height: SIZE }); const data = png.data; // 填充透明背景 for (let y = 0; y < SIZE; y++) { for (let x = 0; x < SIZE; x++) { const idx = (SIZE * y + x) << 2; data[idx] = 0; data[idx + 1] = 0; data[idx + 2] = 0; data[idx + 3] = 0; } } // 绘制图标 draw(png, color); return PNG.sync.write(png); } // 绘制像素 function setPixel(png, x, y, color, alpha = 255) { const idx = (SIZE * y + x) << 2; png.data[idx] = color[0]; png.data[idx + 1] = color[1]; png.data[idx + 2] = color[2]; png.data[idx + 3] = alpha; } // 绘制圆角矩形 function drawRoundRect(png, x, y, w, h, r, color) { for (let dy = 0; dy < h; dy++) { for (let dx = 0; dx < w; dx++) { const px = x + dx; const py = y + dy; // 检查是否在圆角内 let inCorner = false; if (dx < r && dy < r) { // 左上角 const dist = Math.sqrt((r - dx - 1) ** 2 + (r - dy - 1) ** 2); inCorner = dist > r; } else if (dx >= w - r && dy < r) { // 右上角 const dist = Math.sqrt((dx - w + r) ** 2 + (r - dy - 1) ** 2); inCorner = dist > r; } else if (dx < r && dy >= h - r) { // 左下角 const dist = Math.sqrt((r - dx - 1) ** 2 + (dy - h + r) ** 2); inCorner = dist > r; } else if (dx >= w - r && dy >= h - r) { // 右下角 const dist = Math.sqrt((dx - w + r) ** 2 + (dy - h + r) ** 2); inCorner = dist > r; } if (!inCorner) { setPixel(png, px, py, color); } } } } // 绘制圆形 function drawCircle(png, cx, cy, r, color) { for (let y = -r; y <= r; y++) { for (let x = -r; x <= r; x++) { if (x * x + y * y <= r * r) { setPixel(png, cx + x, cy + y, color); } } } } // 绘制矩形 function drawRect(png, x, y, w, h, color) { for (let dy = 0; dy < h; dy++) { for (let dx = 0; dx < w; dx++) { setPixel(png, x + dx, y + dy, color); } } } // 工作台图标 - 网格 function drawWork(png, color) { const s = 12; // 间距 const b = 16; // 方块大小 const ox = 18; // 偏移 const oy = 18; drawRoundRect(png, ox, oy, b, b, 3, color); drawRoundRect(png, ox + b + s, oy, b, b, 3, color); drawRoundRect(png, ox, oy + b + s, b, b, 3, color); drawRoundRect(png, ox + b + s, oy + b + s, b, b, 3, color); } // 订单图标 - 清单 function drawOrder(png, color) { const x = 22, y = 16, w = 36, h = 48; // 外框 drawRoundRect(png, x, y, w, h, 4, color); // 内部线条(用背景色) const bgColor = [0, 0, 0]; drawRect(png, x + 8, y + 12, 20, 3, bgColor); drawRect(png, x + 8, y + 22, 16, 3, bgColor); drawRect(png, x + 8, y + 32, 18, 3, bgColor); } // 设备图标 - 盒子 function drawDevice(png, color) { const x = 18, y = 22, w = 44, h = 36; drawRoundRect(png, x, y, w, h, 6, color); // 屏幕 const bgColor = [0, 0, 0]; drawRoundRect(png, x + 6, y + 6, w - 12, h - 12, 3, bgColor); // 底座 drawRect(png, x + 16, y + h, 12, 6, color); drawRect(png, x + 10, y + h + 6, 24, 3, color); } // 我的图标 - 人形 function drawMy(png, color) { // 头部 drawCircle(png, 40, 26, 12, color); // 身体 drawRoundRect(png, 20, 42, 40, 24, 10, color); } // 生成图标 const icons = [ { name: 'work', draw: drawWork }, { name: 'order', draw: drawOrder }, { name: 'device', draw: drawDevice }, { name: 'my', draw: drawMy }, ]; const outputDir = path.join(__dirname, '../src/static/tabbar'); icons.forEach(({ name, draw }) => { // 普通状态 const inactivePng = createIcon(draw, INACTIVE_COLOR); fs.writeFileSync(path.join(outputDir, `${name}.png`), inactivePng); console.log(`Created ${name}.png`); // 选中状态 const activePng = createIcon(draw, ACTIVE_COLOR); fs.writeFileSync(path.join(outputDir, `${name}-active.png`), activePng); console.log(`Created ${name}-active.png`); }); console.log('All icons generated!');