UNPKG

spritegen-png-cli

Version:

从图标文件夹中生成Maplibre/Mapbox精灵图

94 lines (80 loc) 3.25 kB
import fs from 'fs'; import path from 'path'; import fg from 'fast-glob'; import chokidar from 'chokidar'; import Jimp from 'jimp'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); const Spritesmith = require('spritesmith'); export async function buildSprites(options) { const { input, out, name, padding, ext, ratios, scale2x, watch } = options; const exts = ext.split(',').map(e => e.trim().toLowerCase()); const ratioList = ratios.split(',').map(r => Number(r.trim())); const build = async () => { const files = await fg(exts.map(e => `${input}/**/*.${e}`)); if (!files.length) { console.warn('[spritegen] No images found.'); return; } // build 1x const result1x = await runSpritesmith(files, Number(padding)); await writeOutput(result1x, out, name, 1); // build other ratios for (const ratio of ratioList) { if (ratio === 1) continue; if (scale2x && ratio === 2) { const upscaled = await upscale(result1x, 2); await writeOutput(upscaled, out, name, 2); } else { const result = await runSpritesmith(files, Number(padding)); await writeOutput(result, out, name, ratio); } } }; await build(); if (watch) { console.log(`[spritegen] Watching folder: ${input}`); chokidar.watch(input, { ignoreInitial: true }).on('all', build); } } function runSpritesmith(files, padding) { return new Promise((resolve, reject) => { Spritesmith.run({ src: files, padding }, (err, result) => { if (err) reject(err); else resolve(result); }); }); } async function upscale(result, scale) { const img = await Jimp.read(result.image); img.scale(scale); const image = await img.getBufferAsync(Jimp.MIME_PNG); const coords = {}; for (const [file, info] of Object.entries(result.coordinates)) { coords[file] = { x: Math.round(info.x * scale), y: Math.round(info.y * scale), width: Math.round(info.width * scale), height: Math.round(info.height * scale) }; } return { image, coordinates: coords, properties: result.properties }; } async function writeOutput(result, outDir, baseName, ratio) { fs.mkdirSync(outDir, { recursive: true }); const pngPath = path.join(outDir, `${baseName}${ratio === 1 ? '' : `@${ratio}x`}.png`); const jsonPath = path.join(outDir, `${baseName}${ratio === 1 ? '' : `@${ratio}x`}.json`); await fs.promises.writeFile(pngPath, result.image); await fs.promises.writeFile(jsonPath, JSON.stringify(toMetadata(result.coordinates, ratio), null, 2)); console.log(`[spritegen] Generated: ${pngPath}, ${jsonPath}`); } function toMetadata(coordinates, pixelRatio) { const meta = {}; for (const [file, info] of Object.entries(coordinates)) { const name = path.basename(file, path.extname(file)); meta[name] = { ...info, pixelRatio }; } return meta; }