Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

psdjs解析文本图片及路径 #424

Open
confidence68 opened this issue Apr 28, 2024 · 0 comments
Open

psdjs解析文本图片及路径 #424

confidence68 opened this issue Apr 28, 2024 · 0 comments

Comments

@confidence68
Copy link
Owner

前言

之前讲解过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文件解析官网的相关资料很少,都是靠我们自己不断探索,后期我们将会支持更多的功能。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant