/** * TabBar 图标生成脚本 * 运行: node scripts/generateIcons.js * 需要先安装依赖: npm install canvas */ const fs = require('fs'); const path = require('path'); // 尝试使用 canvas,如果没有安装则使用简单的 PNG 生成 let useCanvas = false; let createCanvas; try { const canvas = require('canvas'); createCanvas = canvas.createCanvas; useCanvas = true; } catch (e) { console.log('canvas 未安装,将生成简单的占位图标'); } const imagesDir = path.join(__dirname, '..', 'images'); // 确保 images 目录存在 if (!fs.existsSync(imagesDir)) { fs.mkdirSync(imagesDir, { recursive: true }); } // 图标配置 const icons = [ { name: 'tab-rank', icon: '排', desc: '排名' }, { name: 'tab-match', icon: '赛', desc: '比赛' }, { name: 'tab-points', icon: '分', desc: '积分' }, { name: 'tab-user', icon: '我', desc: '我的' } ]; const normalColor = '#999999'; const activeColor = '#FF6B35'; const size = 81; // 微信推荐 81x81 function generateIconWithCanvas(iconConfig, isActive) { const canvas = createCanvas(size, size); const ctx = canvas.getContext('2d'); // 清空背景(透明) ctx.clearRect(0, 0, size, size); // 绘制圆形背景 ctx.beginPath(); ctx.arc(size / 2, size / 2, size / 2 - 4, 0, Math.PI * 2); ctx.fillStyle = isActive ? activeColor : '#f5f5f5'; ctx.fill(); // 绘制文字 ctx.font = 'bold 32px sans-serif'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillStyle = isActive ? '#ffffff' : normalColor; ctx.fillText(iconConfig.icon, size / 2, size / 2); return canvas.toBuffer('image/png'); } // 简单的 PNG 生成(不依赖 canvas) function generateSimplePNG(iconConfig, isActive) { // 创建一个简单的 1x1 像素的 PNG 作为占位符 // 实际项目中应该使用真实的图标文件 const color = isActive ? [255, 107, 53] : [153, 153, 153]; // RGB // 最简单的 PNG 文件头 + IHDR + IDAT + IEND // 这是一个 8x8 的纯色 PNG const width = 8; const height = 8; // PNG 签名 const signature = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]); // IHDR chunk const ihdr = createChunk('IHDR', Buffer.from([ 0, 0, 0, width, // width 0, 0, 0, height, // height 8, // bit depth 2, // color type (RGB) 0, // compression 0, // filter 0 // interlace ])); // IDAT chunk - 简化的图像数据 const zlib = require('zlib'); const rawData = Buffer.alloc((width * 3 + 1) * height); for (let y = 0; y < height; y++) { rawData[y * (width * 3 + 1)] = 0; // filter byte for (let x = 0; x < width; x++) { const offset = y * (width * 3 + 1) + 1 + x * 3; rawData[offset] = color[0]; rawData[offset + 1] = color[1]; rawData[offset + 2] = color[2]; } } const compressed = zlib.deflateSync(rawData); const idat = createChunk('IDAT', compressed); // IEND chunk const iend = createChunk('IEND', Buffer.alloc(0)); return Buffer.concat([signature, ihdr, idat, iend]); } function createChunk(type, data) { const length = Buffer.alloc(4); length.writeUInt32BE(data.length); const typeBuffer = Buffer.from(type); const crcData = Buffer.concat([typeBuffer, data]); const crc = crc32(crcData); const crcBuffer = Buffer.alloc(4); crcBuffer.writeUInt32BE(crc >>> 0); return Buffer.concat([length, typeBuffer, data, crcBuffer]); } // CRC32 计算 function crc32(data) { let crc = 0xffffffff; const table = getCRC32Table(); for (let i = 0; i < data.length; i++) { crc = table[(crc ^ data[i]) & 0xff] ^ (crc >>> 8); } return crc ^ 0xffffffff; } let crc32Table = null; function getCRC32Table() { if (crc32Table) return crc32Table; crc32Table = new Uint32Array(256); for (let i = 0; i < 256; i++) { let c = i; for (let j = 0; j < 8; j++) { c = (c & 1) ? (0xedb88320 ^ (c >>> 1)) : (c >>> 1); } crc32Table[i] = c; } return crc32Table; } // 生成图标 console.log('开始生成 TabBar 图标...\n'); icons.forEach(iconConfig => { // 生成普通状态图标 const normalPath = path.join(imagesDir, `${iconConfig.name}.png`); const normalBuffer = useCanvas ? generateIconWithCanvas(iconConfig, false) : generateSimplePNG(iconConfig, false); fs.writeFileSync(normalPath, normalBuffer); console.log(`✓ 已生成: ${iconConfig.name}.png (${iconConfig.desc})`); // 生成选中状态图标 const activePath = path.join(imagesDir, `${iconConfig.name}-active.png`); const activeBuffer = useCanvas ? generateIconWithCanvas(iconConfig, true) : generateSimplePNG(iconConfig, true); fs.writeFileSync(activePath, activeBuffer); console.log(`✓ 已生成: ${iconConfig.name}-active.png (${iconConfig.desc} - 选中)`); }); console.log('\n图标生成完成!'); console.log(`图标目录: ${imagesDir}`); if (!useCanvas) { console.log('\n提示: 当前生成的是简单占位图标。'); console.log('如需更好的图标效果,请:'); console.log('1. 安装 canvas: npm install canvas'); console.log('2. 重新运行此脚本'); console.log('或者从 iconfont.cn 下载合适的图标替换'); }