nodejs打包工具,node能做什么 图

  nodejs打包工具,node能做什么 图

  本文将教大家如何使用node编写一个atlas打包工具,有一定的参考价值,希望对大家有所帮助!

  node.js速度课程简介:进入学习

  偶然发现了一个非常有用的跨平台图像编解码库节点——images。

  仔细看了它的API,一个用它做精灵图集的想法产生了。

  于是这个工具sprites-pack-tool就诞生了。

  精灵图集我想大家都很熟悉。

  比如把下面的几张图片合成一张.

  这个图集是通过本文介绍的工具打包和合成的。

  合成图的质量还是很高的。

  

为什么需要使用图集

  

web开发

  在web开发中,我们需要在浏览器中每显示一张图片就请求一次服务器资源。

  比如3次请求每次4k一次请求12k有本质区别,更多时候一个请求不是3 * 4k

  使用atlas使我们能够优化资源加载并提高网站的性能。

  

游戏开发

  在游戏开发中,图集的使用非常重要。无论是一般的帧动画还是svga等动画解决方案,每张图片都不会请求资源。

  更多的时候,我们打包成atlas,atlas打包工具texturepacker很受欢迎。

  其次,游戏场景太多,通常需要一步步加载资源。有时候,一个动画模型少则十几张,多则近百张。

  图集的使用不可或缺.

  让我们来看看如何编写一个atlas打包工具。

  

工具设计

  开发一个atlas打包工具脚本需要哪些技能?

  node.js的编程能力

  二维矩形装箱算法

  然后我们思考如何包装一本地图集。

  我们需要找到需要打包的文件夹。可能有多个或嵌套的文件夹。

  图集是几幅零散图片的组合。

  atlas的大小需要是可配置的。

  尽量压缩图集空间,让每张图片紧密贴合。

  每个文件夹打包成一个图集,需要考虑图片太多的情况。

  可能需要生成atlas需要的json文件来记录图片的位置信息。

  这是我的设计。

  首先我们需要一个打包的对象实例MySpritePackTool,并且支持写配置参数选项。

  /* *图集打包对象*/

  const MySpritePackTool=function(opt){

  this.options={

  //图片太多或太长的文件夹的最大递归数

  maxCount: opt.maxCount 2,

  //要打包的图集的文件路径

  assetsPath: opt.assetsPath,

  //输出文件路径

  outPutPath: opt.outPutPath,

  //图集的最大包装尺寸

  maxSize: {宽度:2048,高度:2048 }

  }

  };然后我们需要输出这个对象,这个对象可以被其他项目引用。

  module . exports=MySpritePackTool;

开始编写脚本

  我们的输入参数越少越好,这就要求我们的程序要遍历文件夹。

  例如,我们有以下目录树:

   -资产

   -索引

  -img-3.png

  -img-4.png

   -登录

  -img-5.png

  -img-1.png

  img-2.png我们需要在每个文件夹下放一本地图册。

  思考: 需要什么样的数据结构?

  首先,为了便于js解析,我们商定了一个对象,

  每一层都需要一个图片信息容器资产;

  包含图片识别密钥;

  一个文件夹名也方便我们以后给图集命名;

  然后在每一层文件夹前设置相同的对象;

  结构如下:

  {

  资产:[

  {

  id: assets/img-1.png ,

  宽度:190,

  身高:187

  },

  .

  ],

  名称:资产,

  关键字: img-1.png,img-2.png,,

  索引:{

  资产:[

  {

  id: assets/index/img-3.png ,

  宽度:190,

  身高:187

  },

  .

  ],

  名称:“索引”,

  关键字:“img-3.png,img-4.png,”

  },

  登录:{

  资产:[

  {

  id:资产/登录/img-5.png ,

  宽度:190,

  身高:187

  }

  ],

  名称:“索引”,

  关键字:“img-5.png”

  },

  不难发现,我们已经可以获得所有需要打包的文件和文件夹。

  那么用程序如何实现呢?

  Nodejsfs模块主要用于递归操作文件夹,输出所需的节点树。

  写的时候注意是图片还是文件夹。

  myspritepacktool . prototype . find all files=function(obj,rootPath) {

  let node files=[];

  if (fs.existsSync(rootPath)) {

  //获取所有文件名

  node files=fs . readdirsync(root path);

  //组装对象

  let name arr=root path . split(/);

  obj[ assets ]=[];

  obj[ name ]=name arr[name arr . length-1];

  obj[ keys ]= ;

  nodeFiles.forEach(item={

  //确定它不是图片路径

  如果(!/(.png)(。jpe?g)$/。测试(项目)){

  let newPath=path.join(rootPath,item);

  //确定现有文件同时是文件夹系统。

  if(fs . exists sync(new path)fs . statsync(new path)。isDirectory()) {

  //console.log(获取新地址,new path);

  obj[item]={ };

  this.findAllFiles(obj[item],new path);

  }否则{

  Console.log(`文件路径:${newPath}不存在!`);

  }

  }否则{

  console . log(` Image path:$ { item } `);

  obj[keys]=item ,;

  设params={ };

  params[ id ]=path . resolve(root path,`)。/$ { item } `);

  //获取图片的宽度和高度

  params[ width ]=images(path . resolve(root path,`。/${item} `))。width();

  params[ height ]=images(path . resolve(root path,`。/${item} `))。height();

  资产。push(参数);

  }

  })

  }否则{

  Console.log(`文件路径:${rootPath}不存在!`);

  }

  这样就可以得到我们需要的节点树。

  

脚本IO

  我们已经完成了对文件夹的操作,接下来需要思考。

  如何把这些零散的图片打包成一张图?

  一个图有两条信息,宽度和高度,实际上是一个长方形。

  我们现在要做的就是把这些面积不同的矩形,放到一个长宽最大的大矩形里。

  跳开图片, 从矩形放置入手

  二维矩形装箱算法有很多,这里我选一个比较简单的。

  先弄一个最大长宽的矩形盒子的。

  我们先放入一个矩形A,这样剩下的区域就有两块:矩形A的右边矩形A的下边

  然后我们继续放入矩形B,可以右后下,然后就有了基于矩形b的两块空白空间.

  以此类推,我们可以把所有合适的矩形都放进去。

  举个例子

  将左边的大矩形放入右边的矩形框中,得到:

  如你所见,我们节省了大量空间,矩形布局非常紧凑。

  如果用代码实现, 是怎么样的呢?

  /**

  *确定宽度和高度w h

  *先在空白区域放一个,剩下的找右边和底部。

  *如果右边有,如果有,放在空白处继续遍历。

  *下面有没有,有就放进去,然后继续遍历。

  */

  const Packer=函数(w,h) {

  this.root={ x: 0,y: 0,宽度:w,高度:h };

  ///* *匹配所有方块*/

  packer . prototype . fit=function(blocks){

  let节点;

  for(设I=0;I块.长度;i ) {

  设block=blocks[I];

  node=this.findNode(this.root,block.width,block . height);

  if(节点){

  let fit=this.findEmptyNode(node,block.width,block . height);

  block . x=fit . x;

  block . y=fit . y;

  block.fit=fit

  }

  }

  }

  /* *找到可以放入的节点*/

  packer . prototype . findnode=function(node,w,h) {

  if (node.used) {

  return this . findnode(node . right area,w,h) this . findnode(node . down area,w,h);

  } else if(node . width=w node . height=h){

  返回节点;

  }否则{

  返回null

  }

  }

  /* *寻找空缺*/

  packer . prototype . findemptynode=function(node,w,h) {

  //删除已经使用的

  node.used=true

  //右空格

  node.rightArea={

  x: node.x w,

  y: node.y,

  宽度:node.width - w,

  高度:高

  };

  //下部空间

  node.downArea={

  x: node.x,

  y: node.y h,

  宽度:节点宽度,

  高度:node.height - h

  }

  返回节点;

  }

  }使用递归,代码量小,但功能强大。

  但是有一个问题,如果超出定长定宽, 或者一个矩形装不完, 我们的算法是不会放入到大矩形中的

  这有点不满意我们对atlas包装的想法。

  所以我们还是需要改进这个算法;

  添加两个变量,一个记录使用的总的区域,一个记录未被装入的矩形

  //记录使用的总面积

  this.usedArea={ width: 0,height: 0 }。

  //记录尚未加载的矩形

  this . level blocks=[];详细代码可以在源代码包装中查看。

  当然, 这里只是最简单的一种二维装箱算法

  还有一种加强版的装箱算法, 我放在源码里了, 这里就不赘述了, 原理基本一致

  现在,我们可以正确地框出矩形,那么如何使用它来处理成图集呢?

  定义一个dealImgsPacking方法并继续处理我们的节点树。

  这里,我们使用我们的配置项maxCount,只是为了打印多个图集。

  然后我们打包的图集以文件夹 + 当前是第几张的形式命名。

  ` ${obj[name](计数?-计数: )} `具体方法如下:

  myspritepacktool . prototype . dealimgspacking=function(obj){

  设count=0;

  if(obj . hasownproperty( assets ){

  let new blocks=obj[ assets ];

  obj[ assets ]=[];

  while(new blocks . length 0 count this . options . maxcount){

  设Packer 1=new Packer(this . options . maxsize . width,this . options . maxsize . height);

  packer 1 . fit(new blocks);

  小型张1={

  maxArea: packer1.usedArea,

  阿特拉斯:新手,

  文件名:` ${obj[name](计数?-计数: )}

  };

  new blocks=packer 1 . level blocks;

  资产。推送(sheets 1);

  数数;

  }

  }

  for(对象中的字母项){

  if (obj[item].hasOwnProperty( assets ){

  this . dealimgspacking(obj[item]);

  }

  }

  }通过这个方法,我们对之前的节点树进行了改造;

  前一个节点树中的assest变成一个数组,每个数组元素代表一个图集信息。

  其结构如下:

  资产:[

  {

  maxArea: {宽度:180,高度:340 },

  图集:[

  {

  id: assets/index/img-3.png ,

  宽度:190,

  身高:187,

  x: 0,

  y: 0

  }

  ],

  文件名:“资产”},

  .

  ]我们可以清楚的得到,打包后的图集的最大宽度和高度是maxArea,每个图集的宽度和高度位置信息是atlas,图集名称fileName。

  接下来,就是最后一步,绘制新的图片,输出图片文件。

  

遍历文件生成节点树

  节点图像的API用于在此绘制和输出图集;

  遍历之前得到的节点树,先画一个maxArea大小的空白图。

  图像(项目[maxarea])。宽度,项目[maxarea]。height)然后遍历一个图集所需的图片信息,在空白图像上绘制每一张图片。

  //绘制空白图像

  让news prites=images(item[ maxArea ])。宽度,项目[maxArea]。身高);

  //绘制地图集

  imgObj.forEach(it={

  news plites . draw(images(it[ id ]),it[x],it[ y ]);

  });然后画一个图集,输出一个。

  newsplites . save(` $ { this . options . output path }/$ { item[ fileName ]} . png `);最后,绘制节点树递归调用的所有图集。

  具体代码如下:

  myspritepacktool . prototype . draw images=function(obj){

  设count=0;

  if(obj . hasownproperty( assets ){

  //打包一个或多个图集。

  let img sinfo=obj[ assets ];

  imgsInfo.forEach(item={

  if(item . hasownproperty( atlas ){

  let imgObj=item[ atlas ];

  //console.log(8888 ,imgObj)

  //绘制透明图像

  让news prites=images(item[ maxArea ])。宽度,项目[maxArea]。身高);

  imgObj.forEach(it={

  news plites . draw(images(it[ id ]),it[x],it[ y ]);

  });

  newsplites . save(` $ { this . options . output path }/$ { item[ fileName ]} . png `);

  数数;

  }

  })

  }

  for(对象中的字母项){

  if (obj[item].hasOwnProperty( assets ){

  this . draw images(obj[item]);

  }

  }

  }这样,我们就完成了,

  运行它,你可以得到下面的图集:

  效果还不错。

  

获取新的图集位置信息

  安装

  NPI精灵包工具的使用

  const MySpritePackTool=require( sprites-pack-tool );

  const path=require( path );

  /* *打包的最大递归数*/

  const MAX _ COUNT=2;

  //要合成的地图的路径

  const assets path=path . resolve(_ _ dirname,。/assets’);

  /* *图集打包工具配置*/

  const mySpritePackTool=new mySpritePackTool({

  //图片太多或太长的文件夹的最大递归数

  maxCount: MAX_COUNT,

  //要打包的图集的文件路径

  资产路径:资产路径,

  //输出文件路径

  output path:path . resolve(_ _ dirname,。/res ),

  //图集的最大包装尺寸

  maxSize: {宽度:2048,高度:2048}

  });

  /* *图集包装*/

  mySpritePackTool。pack 2 sprite();

图集打包并输出

  当然,这个工具只是第一版,以后还会继续优化,增加新的功能。

  算法可以继续优化,现在有很多空白。

  文件夹操作,可以优化。比如写图,可以是每个文件夹里的下一个图集。

  添加更多的配置项,比如打开图像压缩。

  添加json文件

  .

  我粗略看了一下,市面上有几款atlas打包工具,要么基于texturePacker,要么基于imagemagick

  使用这两个开放的API也可以封装图集,效果质量可能会更好。

  但是你必须安装一个额外的应用程序。

  同样,你也可以使用webpack的一些加载器或插件。目的是包装图集。

  本文介绍的工具是轻量级的,但是它们可以开箱即用。

  

如何使用

  有段时间没写文章了。这个周末无意中想写一个这样的工具,就付诸实践了,结果不错。

  如果你有更好的办法,可以留下评论,非常感谢~。

  欢迎大家指正。作者功力尚浅。如有不妥,请指正。

  文章粗浅, 望诸位不吝您的评论和点赞~

  更多关于node的信息,请访问:nodejs教程!以上就是如何使用node开发一个atlas打包工具的细节。请多关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: