psdjs解析文本图片及路径

7776次浏览

前言

之前讲解过psd文件上传,今天分享一下如何解析文字特效,字体大小,字体等等,顺便讲解如何解析路径。

Font-size字体大小

上一节关于矩阵,我已经写了psdjs关于字体解析的transform矩阵,因此,我们可以根据这个矩阵计算出ps里面字体的大小。

解析字体大小的流程:

第一步:取出sizes里面的最大值,psd解析sizes是一个数组,因为ps里面可以针对一个文本框文字设置不同的字体大小,假如你解析可以支持不同字体大小的解析,可以根据length和sizes,或者文本框里面每个文字的字体大小,假如不那么精准,可以获取其中最大的一个就可以了。

第二步:通过上一节里面的矩阵,或者字体的变化大小 Math.round(fsize * item.text.transform.yy)

第三步:纠正,假如解析的字体大于文本框高度,或者小于文本框的一半,那么字体大小应该还是有问题的,可以进一步纠正,可以在字体大于图层的高度的时候,设置字体高度为图层高度。

fontFamily获取

fontFamily我们这边要有对应的在线字体cdn地址,要将psd解析的字体名称和我们在线地址的cdn对应起来,还是有点麻烦。可以通过如下方式:

一、可以通过单个解析psd文件获取字体,要解析所有字体,获取ps里面字体解析的名字做映射关系。

二、可以通过opentype.js获取字体,这个库提供了一个在线地址,如下: https://opentype.js.org/font-inspector.html

enter image description here

上面就是方正宝成字体解析的ps里面名称。

字体特效

在图层参数下面的adjustments下面的objectEffects下面的data可以获取到文字特效相关参数

enter image description here

备注,特效里面很多字是简写,例如Rd是red红色,假如是redFloat需要乘以255

关于图片

图片解析成base64或者uint8Array转换成file上传后台,可以参考https://www.haorooms.com/post/js_file_base64_blob

关于路径

如下代码获取路径

let psdData = psd.tree();
let node = psdData.descendants()[0];
console.log(node, node.get("vectorMask"));
let vectorMask = node.get("vectorMask");
const data = vectorMask.export();
const { paths = [] } = data;
console.log(paths, "paths__");
paths.forEach((path) => {
  // 变量路径节点
  console.log(path, "path___");
});

打印如下:

enter image description here

具体含义可以参考我准备的一个内部分享

enter image description here

解析路径为svg相关代码如下:

// 转化无符号浮点数
const signed = function (n) {
  let num = n;
  if (num > 0x8f) {
    num = num - 0xff - 1;
  }
  return num;
};
const getPathPosition = function (pathNode) {
  const { vert, horiz } = pathNode;
  return {
    x: signed(horiz),
    y: signed(vert),
  };
};

const parsePath = function (path, { width, height }) {
  const { preceding, anchor, leaving } = path;
  const precedingPos = this.getPathPosition(preceding);
  const anchorPos = this.getPathPosition(anchor);
  const leavingPos = this.getPathPosition(leaving);
  // relX 和 relY 保留了PSD中原始数据。
  return {
    preceding: {
      relX: precedingPos.x,
      relY: precedingPos.y,
      x: Math.round(width * precedingPos.x),
      y: Math.round(height * precedingPos.y),
    },
    anchor: {
      relX: anchorPos.x,
      relY: anchorPos.y,
      x: Math.round(width * anchorPos.x),
      y: Math.round(height * anchorPos.y),
    },
    leaving: {
      relX: leavingPos.x,
      relY: leavingPos.y,
      x: Math.round(width * leavingPos.x),
      y: Math.round(height * leavingPos.y),
    },
  };
};

const getFillColor = function (node) {
  const solidColorData = node.get("solidColor");
  const clr = solidColorData["Clr "];
  return colorHex([
    Math.round(clr["Rd "]),
    Math.round(clr["Grn "]),
    Math.round(clr["Bl "]),
  ]);
};

const toPath = (paths, fill) => {
  let head;
  const data = [];
  paths.forEach((path, index) => {
    const { preceding, anchor, leaving } = path;
    if (index < paths.length - 1) {
      if (index > 0) {
        // 中间节点
        data.push(
          `${preceding.x}, ${preceding.y} ${anchor.x}, ${anchor.y} ${leaving.x}, ${leaving.y}`
        );
      } else {
        // 记录第一个节点,用于在关闭路径的时候使用
        head = path;
        data.push(`M ${anchor.x}, ${anchor.y} C${leaving.x}, ${leaving.y}`);
      }
    } else {
      data.push(`${preceding.x}, ${preceding.y} ${anchor.x}, ${anchor.y} ${leaving.x}, ${leaving.y} ${head.preceding.x},
            ${head.preceding.y} ${head.anchor.x}, ${head.anchor.y} Z`);
    }
  });
  return `<path d="${data.join(" ")}" fill="${fill}" />`;
};

小结

psd文件解析官网的相关资料很少,都是靠我们自己不断探索,后期我们将会支持更多的功能。

Tags: psd.js,js

相关文章: