【问题标题】:Split a svg path d to array of objects将 svg 路径 d 拆分为对象数组
【发布时间】:2020-11-21 16:09:45
【问题描述】:

有没有办法将d 路径字符串拆分为对象数组?

例如:

const d = `M 0 0 L 0 10 C 0 10 20 30 20 20 Z`
const result = fromPathToArray(d)

// const result = [
//   { type: 'M', x: 0, y: 0 },
//   { type: 'L', x: 0, y: 10 },
//   { type: 'C', x1: 0, y1: 10, x2: 20, y2: 30, x3: 20, y3: 20 },
//   { type: 'Z' },
// ]

这是我的起始代码:

const PATH_COMMANDS = {
  M: ["x", "y"],
  m: ["dx", "dy"],
  H: ["x"],
  h: ["dx"],
  V: ["y"],
  v: ["dy"],
  L: ["x", "y"],
  l: ["dx", "dy"],
  Z: [],
  C: ["x1", "y1", "x2", "y2", "x", "y"],
  c: ["dx1", "dy1", "dx2", "dy2", "dx", "dy"],
  S: ["x2", "y2", "x", "y"],
  s: ["dx2", "dy2", "dx", "dy"],
  Q: ["x1", "y1", "x", "y"],
  q: ["dx1", "dy1", "dx", "dy"],
  T: ["x", "y"],
  t: ["dx", "dy"],
  A: ["rx", "ry", "rotation", "large-arc", "sweep", "x", "y"],
  a: ["rx", "ry", "rotation", "large-arc", "sweep", "dx", "dy"]
};

export function splitPath(path) {
  const items = path.trim().split(/\s*,|\s+/);
  const segments = [];
  
  items.forEach((item, i) => {
    const type = isString(item) ? item : null
    // ...
  })

  return segments
}

老实说我不知道​​该怎么做..

【问题讨论】:

  • 除了“a 4.12.12 001 4.13-1”是一个完全有效的弧命令,有 7 个参数,因为 001 算作 3 个参数。您必须知道这些标志参数中的每一个都是 1 个字符。同样你也必须知道 4.12.12 实际上被解析为 4.12, 0.12 而 4.12-1 是 4.12, -1
  • 有很多path data parsers你可以试试。 @RobertLongson a 4.12.12 001 4.13-1 不是有效的 arc 命令。 001 将被读取为旋转 = 1。你指的是a 4.12.12 0 014.13-1
  • 啊,是的。关闭但没有雪茄。您还可以重复所有参数,它们算作该类型的附加命令(M、m 除外,它变成了 L、l)。不知道你将如何存储它。
  • Fabric JS 已经实现了类似的东西,将它作为一个字符串返回一个结构对象,它将它们分成数组,如果你愿意,你可以反过来将其转换为点。我想你可以在这里找到相关代码:fabricjs.com/docs/fabric.js.html#line4822(警告这是一个沉重的页面,因为它指向一个巨大的源文件)

标签: javascript svg


【解决方案1】:

对于您所描述的情况,这是一个简单的例程。请注意,这种简单的解决方案只有在您知道输入遵循某种模式时才有用。如 cmets 所示,一般情况更复杂。此外,您应该添加完整性检查来处理错误输入。

const PATH_COMMANDS = {
  M: ["x", "y"],
  m: ["dx", "dy"],
  H: ["x"],
  h: ["dx"],
  V: ["y"],
  v: ["dy"],
  L: ["x", "y"],
  l: ["dx", "dy"],
  Z: [],
  C: ["x1", "y1", "x2", "y2", "x", "y"],
  c: ["dx1", "dy1", "dx2", "dy2", "dx", "dy"],
  S: ["x2", "y2", "x", "y"],
  s: ["dx2", "dy2", "dx", "dy"],
  Q: ["x1", "y1", "x", "y"],
  q: ["dx1", "dy1", "dx", "dy"],
  T: ["x", "y"],
  t: ["dx", "dy"],
  A: ["rx", "ry", "rotation", "large-arc", "sweep", "x", "y"],
  a: ["rx", "ry", "rotation", "large-arc", "sweep", "dx", "dy"]
};

function fromPathToArray(path) {
  const items = path.replace(/[\n\r]/g, '').
                replace(/-/g, ' -').
                replace(/(\d*\.)(\d+)(?=\.)/g, '$1$2 ').
                trim().
                split(/\s*,|\s+/);
  const segments = [];
  let currentCommand = '';
  let currentElement = {};
  while (items.length > 0){
    let it = items.shift();
    if (PATH_COMMANDS.hasOwnProperty(it)){
      currentCommand = it;
    }
    else{
      items.unshift(it);
    }
    currentElement = {type: currentCommand};
    PATH_COMMANDS[currentCommand].forEach((prop) => {
      it = items.shift();  // TODO sanity check
      currentElement[prop] = it;
    });
    if (currentCommand === 'M'){
      currentCommand = 'L';
    }
    else if (currentCommand === 'm'){
      currentCommand = 'l';
    }
    segments.push(currentElement);
  }
  return segments
}

const d = `M 0 0 10 10 L 0 10 C 0 10 
20 30 20 20 a 4.12.12 1 0 1 4.13-1 Z`;
const result = fromPathToArray(d);

console.log(result);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-20
    • 2020-11-24
    • 2022-01-22
    • 1970-01-01
    • 2020-04-07
    • 2015-10-16
    相关资源
    最近更新 更多