当前位置: 首页 > wzjs >正文

上海网站推广优化公司2021全国大学生营销大赛

上海网站推广优化公司,2021全国大学生营销大赛,域名哪里注册,响应式网站建设推荐乐云seo概述 精灵图(Sprite)是一种将多个小图像合并到单个图像文件中的技术,广泛应用于网页开发、游戏开发和UI设计中。在MapboxGL中,跟之配套的还有一个json文件用来记录图标的大小和位置。本文分享基于Node和sharp库实现精灵图的合并与…

概述

精灵图(Sprite)是一种将多个小图像合并到单个图像文件中的技术,广泛应用于网页开发、游戏开发和UI设计中。在MapboxGL中,跟之配套的还有一个json文件用来记录图标的大小和位置。本文分享基于Node和sharp库实现精灵图的合并与拆分。

实现效果

拆分后的图片

合并后的精灵图

合并后精灵图的json文件
运行时的截图

代码实现

将拆分和合并封装成了一个方法,实现代码如下:

const sharp = require("sharp");
const fs = require("fs").promises;
const path = require("path");// 二叉树节点类
class Node {constructor(x, y, width, height) {this.x = x;this.y = y;this.width = width;this.height = height;this.used = false;this.right = null;this.down = null;}// 查找可以放置图片的节点find(width, height) {// 如果当前节点已被使用,在子节点中查找if (this.used) {return this.right?.find(width, height) || this.down?.find(width, height);}// 检查图片是否适合当前节点if (width <= this.width && height <= this.height) {return this;}return null;}// 分割节点split(width, height) {this.used = true;// 创建右侧节点this.right = new Node(this.x + width, this.y, this.width - width, height);// 创建底部节点this.down = new Node(this.x,this.y + height,this.width,this.height - height);return this;}
}class SpriteManager {constructor() {this.metadata = {sprites: {},width: 0,height: 0,};}/*** 将多个图片合并成一个精灵图* @param {string} inputDir 输入图片目录* @param {string} outputImage 输出精灵图路径* @param {string} outputJson 输出JSON文件路径*/async createSprite(inputDir, outputImage, outputJson) {const start = Date.now();try {// 读取目录下所有图片const files = await fs.readdir(inputDir);const images = files.filter((file) => /\.(png|jpg|jpeg)$/i.test(file));// 并行处理图片元数据const imageMetadata = await Promise.all(images.map(async (file) => {const imagePath = path.join(inputDir, file);const image = sharp(imagePath);const metadata = await image.metadata();const name = file.split(".")[0];// 预处理图片 - 统一转换为PNG格式并缓存const buffer = await image.png().toBuffer();return {name,width: metadata.width,height: metadata.height,buffer,};}));// 按面积从大到小排序imageMetadata.sort((a, b) => b.width * b.height - a.width * a.height);// 计算初始画布大小const totalArea = imageMetadata.reduce((sum, img) => sum + img.width * img.height,0);const estimatedSide = Math.ceil(Math.sqrt(totalArea * 1.1));// 创建根节点let root = new Node(0, 0, estimatedSide, estimatedSide);let maxWidth = 0;let maxHeight = 0;// 使用二叉树算法放置图片for (const img of imageMetadata) {// 查找合适的节点let node = root.find(img.width, img.height);// 如果找不到合适的节点,扩展画布if (!node) {// 创建新的更大的根节点const newRoot = new Node(0, 0, root.width * 1.5, root.height * 1.5);newRoot.used = true;newRoot.down = root;root = newRoot;node = root.find(img.width, img.height);}// 分割节点并记录位置if (node) {const position = node.split(img.width, img.height);this.metadata.sprites[img.name] = {x: position.x,y: position.y,width: img.width,height: img.height,};// 更新最大尺寸maxWidth = Math.max(maxWidth, position.x + img.width);maxHeight = Math.max(maxHeight, position.y + img.height);}}// 更新最终画布尺寸this.metadata.width = maxWidth;this.metadata.height = maxHeight;// 创建并合成图片const composite = sharp({create: {width: this.metadata.width,height: this.metadata.height,channels: 4,background: { r: 0, g: 0, b: 0, alpha: 0 },},});// 一次性合成所有图片const compositeOperations = imageMetadata.map((img) => ({input: img.buffer,left: this.metadata.sprites[img.name].x,top: this.metadata.sprites[img.name].y,}));await composite.composite(compositeOperations).png({ quality: 100 }).toFile(outputImage);// 保存JSON文件await fs.writeFile(outputJson, JSON.stringify(this.metadata.sprites));const end = Date.now();console.log("精灵图创建完成, 耗时" + (end - start) / 1000 + "s");} catch (error) {throw new Error(`创建精灵图失败: ${error.message}`);}}/*** 从精灵图中提取单个图片* @param {string} spriteImage 精灵图路径* @param {string} jsonFile JSON文件路径* @param {string} outputDir 输出目录*/async extractSprites(spriteImage, jsonFile, outputDir) {// 读取JSON文件const metadata = JSON.parse(await fs.readFile(jsonFile, "utf-8"));// 确保输出目录存在await fs.mkdir(outputDir, { recursive: true });// 提取每个图片for (const [filename, info] of Object.entries(metadata)) {const iconPath = path.join(outputDir, filename + ".png");sharp(spriteImage).extract({left: info.x,top: info.y,width: info.width,height: info.height,}) // 裁剪区域.toFile(iconPath).then((_info) => {console.log("Image cropped successfully:", _info);}).catch((error) => {console.log(iconPath, info);console.error("Error processing image:", error);});}}
}module.exports = SpriteManager;

调用代码如下:

// 引用
const SpriteManager = require("./sprite/sprite");const spriteManager = new SpriteManager();// 创建精灵图
spriteManager.createSprite("./sprite/icons", // 输入图片目录"./sprite/sprite.png", // 输出精灵图路径"./sprite/sprite.json" // 输出JSON文件路径
);
// 拆分精灵图
// spriteManager.extractSprites(
//   "./sprite/sprite.png", // 精灵图路径
//   "./sprite/sprite.json", // JSON文件路径
//   "./sprite/icons" // 输出目录
// );
http://www.dtcms.com/wzjs/297657.html

相关文章:

  • h5自适应企业网站源码网站百度不收录的原因
  • 黄骅贴吧海鲜城正规seo大概多少钱
  • 如何给网站增加关键词铜川网站seo
  • 专门做二手手机的网站吗网络服务有限公司
  • 重庆 机械有限公司 沙坪坝网站建设沈阳今日新闻头条
  • 兰州响应式网站建设简述如何优化网站的方法
  • 个人动漫网站怎么做页面windows优化大师好不好
  • 珠海网站设计网络优化个人怎么做网站
  • 日本做任务赚钱的网站有哪些南宁百度seo软件
  • 企业网站建设对网络营销的影响网上营销是做什么的
  • 网站建设哪家好 上海网络推广是什么工作
  • 关于建设网站的图片seo网站优化系统
  • 彩票网站开发制作全网整合营销推广系统
  • iis发布php网站免费发布信息
  • 大连学网站制作软件开发培训班
  • dw做网站的实用特效企业培训课程体系
  • 网站建设和优全媒体运营师报名入口
  • 做网站是否要备案三亚网络推广
  • 局域网内建网站百度首页百度
  • 电商大数据平台建设方案seo需要什么技术
  • 个人做企业 网站seo前线
  • 女性pose拍照seo文章是什么
  • 阿里云最低服务器可以做几个网站seo优化网站模板
  • 网站没备案怎么做广告联盟百度官方客服平台
  • 徐州企业做网站网站建网站建设网站
  • 继续网站建设百度霸屏推广一般多少钱
  • 贵州做团队培训的网站指数函数和对数函数
  • magento 做的最牛逼的中文网站新手如何涨1000粉
  • 襄阳电商网站建设手机管家一键优化
  • 东莞做网站找微客巴巴aso优化{ }贴吧