首页 文章

在Inkscape中展平SVG矩阵变换

提问于
浏览
37

我有一个最初在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>

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

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

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

IE10 path only

IE10 path with transform

Inkscape path only

Inkscape path with transform

5 回答

  • 13

    简答

    在Inkscape中键入变换矩阵参数时,请确保已选中"Edit current matrix",因为如果将新变换矩阵应用于对象,则实际上是将此新矩阵与对象的现有变换矩阵相乘,因此请确保编辑相反 .

    enter image description here

    答案很长

    如何自己重新计算一切 .

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

    transformation matrix

    计算 x'y' 是这样完成的:

    x' = a*x + c*y + e 
    y' = b*x + d*y + f
    

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

    <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
    

    现在,如果我们有以下示例坐标: 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
    

    整洁,对吧?你可以获得更多信息here

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

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

    <path d="M486,313s27-9,43-29l26,4,1,23-22,5s-25-6-48-3z" />
    

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

    M486,313 被转换为绝对移动到x = 486,y = 313
    s27-9,43-29 读起来有点复杂,因为有些coma被省略了,因为如果负数是负数则不需要它们,所以减号充当昏迷 - 无论如何,它转换为相对平滑的bezier曲线到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" />
    

    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
    

    现在转到指令 M524.589,200.892

    S27-9,43-29 - smooth curveto,为每个坐标重复相同的过程,但将 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" />
    

    我希望这对你有意义 .

  • 2

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

  • 18

    Paste In Place 可以帮到你:

    在Inkscape中

    • Double click the group ,输入它 .
      009 Select all 按Ctrl A按组的内容,按Ctrl C按 copy

    • Double click outside 该组离开该组 .

    • 编辑> Paste In Place (Ctrl Alt V) - 此时,组变换将应用于您粘贴的对象 .
      再次

    • Group 个对象(Ctrl G)

    • 将新组移动到与原始组相同的深度,并 delete the original group . (使用XML编辑器Ctrl Shift X可能更容易 . )

  • 51

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

  • 11

    感谢ArtBIT提供的所有信息!我在PHP应用程序上遇到了一些问题,并编写了一个操作字体数据的库(来自SVG文件)并对其进行任何类型的转换 . 任何有兴趣的人都可以试试GitHub:

    https://github.com/kartsims/easysvg

    用法示例:

    require 'easySVG.php';
    $svg = new EasySVG();
    $svg->setFont("paris-bold-webfont.svg", 100, "#000000");
    $svg->addText("Simple text display");
    $svg->addAttribute("width", "800px");
    $svg->addAttribute("height", "100px");
    echo $svg->asXML();
    

    SVG数据操作示例:

    $def = 'YOUR SVG DEFINITION HERE';
    $easySVG = new EasySVG();
    // rotate by 40°
    $rotated_def = $easySVG->defRotate($def, 40)
    // rotate by 40° with center at (200,100)
    $rotated_def2 = $easySVG->defRotate($def, 40, 200, 100)
    // scale transform : width*4
    $scaled_def = $easySVG->defScale($def, 4)
    

相关问题