调整 SVG 图形的原点

Adjust origin of SVG graphic

tl;dr:给定任意 SVG <path> 如何调整路径命令以设置文件的新原点?

详情

我正在使用 Adob​​e Illustrator 创建用于 Android 的矢量图形。 Illustrator 有 a bug 在(未知)情况下 viewBox 和为您的图形创建的所有坐标与您为 canvas 设置的坐标不匹配和 Illustrator 中的对象。而不是(例如)viewBox="-7 0 14 20" 你可能会得到 viewBox="-53 75 14 20"。通常,路径命令将被翻译以适应该 viewBox。有时甚至会失败。

在普通的 SVG 文件中 (a) 这几乎不会被注意到,并且 (b) 通过将所有内容包装在根级别 <g transform="translate(46,-75)"> 中很容易修复。在 Android VectorDrawable 中,这需要一个我不想添加的额外 <group>,并且(与 SVG 不同)我无法向 <path> 本身添加翻译.在我的代码中,来源很重要。

如何调整 SVG 文件中所有路径的路径命令以将它们偏移固定量,从而允许我将原点放在我想要的位置?

A 解决方案是在每个要调整的路径上显式添加 transform="translate(…,…)",在网络浏览器中查看 SVG,使用 [=12 中的代码=] [注:我自己的]将translate烘焙成路径数据,然后使用Web inspector获取变化后的值。很麻烦。


更好:我创建了一个在线小工具SVG Reoriginizer[没有广告,没有收入],可以让您将 SVG 代码粘贴到顶部框中,点击 (或使用alt+shift+箭头键)调整原点,看到底部显示的翻译路径命令。

核心代码是这个函数,它将viewBox和所有绝对路径命令偏移指定的量,并且returns改变后的SVG作为字符串:

function offsetOrigin(svg,dx,dy){
  svg.viewBox.baseVal.x -= dx;
  svg.viewBox.baseVal.y -= dy;
  [].forEach.call(svg.querySelectorAll('path'),function(path){
    var segs = path.pathSegList;
    for (var i=segs.numberOfItems;i--;){
      var seg=segs.getItem(i), c=seg.pathSegTypeAsLetter;
      if (/[MLHVCSQTA]/.test(c)){
        if ('x'  in seg) seg.x -=dx;
        if ('y'  in seg) seg.y -=dy;
        if ('x1' in seg) seg.x1-=dx;
        if ('x2' in seg) seg.x2-=dx;
        if ('y1' in seg) seg.y1-=dy;
        if ('y2' in seg) seg.y2-=dy;
      }
    }
  });

  return (new XMLSerializer).serializeToString(svg);
}