在Inkscape中展平SVG矩阵变换

Tom*_*all 38 svg transform matrix inkscape

我有一个最初在Inkscape中创建的免费剪贴画SVG文件,我正在修改它以用于Windows 8 JavaScript游戏.它包含许多路径实例,并在周围的组上应用矩阵变换,如下所示:

<g transform="matrix(0.443,0.896,-0.896,0.443,589.739,-373.223)">
    <path d="M486,313s27-9,43-29l26,4,1,23-22,5s-25-6-48-3z" />
</g>
Run Code Online (Sandbox Code Playgroud)

我希望通过将它预先应用到Inkscape中的路径来展平该转换,以减少动画期间的浏览器工作.然而,当我将6个矩阵值插入Inkscape中的ABCDEF参数并应用它时,它为路径提供了完全不同的旋转和缩放到IE10引擎的功能.

我已经多次检查过我正确映射了6个值.我究竟做错了什么?

编辑:好的,这里是IE10和Inkscape的截图之前和之后.对于IE10的情况,SVG直接驻留在一个空的HTML文档的主体内(Firefox中的渲染完全相同).在Inkscape中,我只是打开了"之前"SVG文件,该文件只包含路径元素,选择了路径,并将6个矩阵变换值插入到Object> Transform> Matrix中.我对矩阵知之甚少,我只是希望能够以与浏览器相同的方式预先应用这些转换,并且理想地理解为什么Inkscape存在差异.谢谢.

仅限IE10路径 IE10路径与变换 仅限Inkscape路径 Inkscape路径与变换

Art*_*BIT 55

简短的回答

在Inkscape中键入变换矩阵参数时,请确保选中"编辑当前矩阵",因为如果将新变换矩阵应用于对象,则实际上将此新矩阵与对象的现有变换矩阵相乘,因此确保你改为编辑它.
在此输入图像描述

答案很长

如何自己重新计算一切.

首先让我们尝试理解转换矩阵.变换矩阵是一种快速而聪明的工具,用于将仿射变换(保留直线的变换)应用于矢量.
因此,如果您有一个向量(比如,2d坐标)和一个变换矩阵,并将两者相乘,您将最终得到变换坐标,并应用变换矩阵中定义的变换.
变换矩阵
计算x'y'完成如下:

x' = a*x + c*y + e 
y' = b*x + d*y + f
Run Code Online (Sandbox Code Playgroud)

接下来,我们需要了解一下svg格式.
根据w3c svg规范,matrix变换正好将这6个参数(a,b,c,d,e,f)作为参数.
因此,从你的例子来看,

<g transform="matrix(0.443,0.896,-0.896,0.443,589.739,-373.223)">
Run Code Online (Sandbox Code Playgroud)

我们有以下转换矩阵参数:

a=0.443
b=0.896
c=-0.896
d=0.443
e=589.739
f=-373.223
Run Code Online (Sandbox Code Playgroud)

现在,如果我们有以下示例坐标:x=27, y=-9,我们可以使用之前定义的转换矩阵对其进行转换,如下所示:

x' = a*x + c*y + e 
x' = 0.443*27 + -0.896*-9 + 589.739
x' = 609.764

y' = b*x + d*y + f
y' = 0.896*27 + 0.443*-9 -373.223
y' = ?353.018
Run Code Online (Sandbox Code Playgroud)

整洁,对吧?你可以在这里获得更多信息

但这还不是全部.我们还需要了解svg路径数据.
根据w3c svg路径dspecification,路径数据中的每个字母代表一条指令.并且指令后面的每个数字对代表坐标值.

从您的示例中,我们有以下路径:

<path d="M486,313s27-9,43-29l26,4,1,23-22,5s-25-6-48-3z" />
Run Code Online (Sandbox Code Playgroud)

这里我们看到这个路径对象使用一个绝对moveto指令(大写M),一个相对smooth curveto立方贝塞尔曲线(小写s),一个相对lineto指令(小写l)和另一个相对smooth curveto立方贝塞尔曲线指令,后跟一条closepath指令(小写z) .

M486,313被翻译为绝对移动到x = 486,y = 313
s27-9,43-29有点复杂,因为有些昏迷被省略,因为如果负数是负数则不需要它们,所以减号就像昏迷一样 - 无论如何,它翻译到相对平滑的贝塞尔曲线到x = 27,y = -9,x = 43,y = -29(一个目标点和一个控制点)
依此类推.

那么,我们如何应用和删除svg组中的转换矩阵?像这样:

// we read the transformation matrix params
// <g transform="matrix(0.443,0.896,-0.896,0.443,589.739,-373.223)">
a=0.443
b=0.896
c=-0.896
d=0.443
e=589.739
f=-373.223

// we read the path data, and transform each instruction    
// <path d="M486,313s27-9,43-29l26,4,1,23-22,5s-25-6-48-3z" />
Run Code Online (Sandbox Code Playgroud)

M486,313绝对搬家了

x' = a*x + c*y + e = a*486 + c*313 + e = 524.589
y' = b*x + d*y + f = b*486 + d*313 + f = 200.892
Run Code Online (Sandbox Code Playgroud)

现在移至指令M524.589,200.892

S27-9,43-29 - 平滑曲线,对每个坐标重复相同的过程,但将ef(平移参数)设置为0,因为它是相对指令而不是绝对.
现在是
s20.025,20.205,45.033,25.680999999999997

l26,4,1,23-22,5
将变为
l7.934000000000001,25.067999999999998,-20.165,11.085,-14.226,-17.497

s-25-6-48-3
将成为
s-5.698999999999999,-25.058000000000003,-18.576,-44.337

并且z将保持z

因此,生成的转换路径将是:

<path d="M524.589,200.892s20.025,20.205,45.033,25.680999999999997l7.934000000000001,25.067999999999998,-20.165,11.085,-14.226,-17.497s-5.698999999999999,-25.058000000000003,-18.576,-44.337z" />
Run Code Online (Sandbox Code Playgroud)

我希望这对你有意义.

  • 请注意,如果您希望最终外观相同,则通常不能将元素转换为其数据(即使对于`<path>`)."skew"的存在尤其以不能仅用路径命令表示的方式非均匀地改变笔划的外观. (4认同)
  • @TomHall确保你取消对象的对象(对象 - >取消组合或<SHIFT + CTRL + G>)并保存为优化的.svg (3认同)
  • 但是我作为测试操作的 SVG 文件只有一个直接位于 SVG 节点内部的路径节点(我的问题的路径)。所以过程是:我打开它,应用变换并勾选“编辑当前矩阵”并将存储变换设置为“优化”,然后尝试取消分组,然后另存为优化的 SVG。但它保存了添加的变换,如下所示: &lt;path d="m486,313s27-9,43-29l26,4,1,23-22,5s-25-6-48-3z" transform="matrix(0.443, 0.896,-0.896,0.443,589.739,-373.223)"/&gt; 抱歉,我太迟钝了,我做错了什么? (2认同)

par*_*dio 19

您可以使用路径 - >联合(CTRL ++)烘焙选择路径的坐标.希望这可以帮助

  • 注意:如果路径没有关闭,这将改变路径. (4认同)

and*_*par 15

粘贴到位可以帮助您:

  1. 双击 Inkscape中的组,输入它.
  2. 按Ctrl + A 选择组中的所有内容,然后使用Ctrl + C 复制它们.
  3. 双击外部以离开组.
  4. 编辑> 粘贴到位(Ctrl + Alt + V)- 此时,组转换将应用于您粘贴的对象.
  5. 再次对对象进行分组(Ctrl + G)
  6. 将新组移动到与原始组相同的深度,然后删除原始组.(使用XML编辑器,Ctrl + Shift + X可能更容易.)


bte*_*tel 11

根据@andraaspar的答案,您还可以尝试取消组合(Ctrl-U)并再次分组(Ctrl-G).它对我有用.