SVG变换的应用顺序

25
W3C的规范中,它说:
“‘transform’属性的值是一个,它被定义为一系列变换定义,按照提供的顺序应用。如果提供了一系列变换,则净效果就好像每个变换都是按照提供的顺序单独指定的。”
当我在Firefox、Chrome和IE10中尝试使用以下标记时,所有三个浏览器都通过先进行翻译,然后再进行旋转来呈现!请参见codepen片段。我错过了什么?还是这三个浏览器的实现不符合W3C标准?
<svg width="180" height="200"
  xmlns="http://www.w3.org/2000/svg" 
  xmlns:xlink="http://www.w3.org/1999/xlink">

  <!-- This is the element before translation and rotation are applied -->
  <rect x="0" y="0" height="100" width="100" style="stroke:#000; fill: #0086B2" fill-opacity=0.2 stroke-opacity=0.2></rect>

  <!-- Now we add a text element and apply rotate and translate to both -->
  <rect x="0" y="0" height="100" width="100" style="stroke:#000; fill: #0086B2" transform="rotate(45 100 50) translate(50)"></rect>
</svg>

1
通过快速在codepen上测试,似乎证实了我之前怀疑的事情。翻译取决于旋转角度。比如你开始时有一辆车朝北行驶,如果向前移动5米,你就向北移动了5米。但是如果你将汽车顺时针旋转45°,然后向前行驶5米,你就会以东北方向前进5米。所以你需要做以下两件事:(1)如果可能的话将变换矩阵重置(应用)到对象上——就像在3D内容创建软件Blender、Maya、3dsMax等中所做的那样。(2)需要计算一个旋转后的平移向量。 - enhzflep
2个回答

27

规范文件很清楚地规定了应用变换的顺序,即最右边的变换首先被应用。

如果提供了多个变换,则按照提供的顺序逐个应用,最终效果等同于分别指定每个变换。

即,

<g transform="translate(-10,-20) scale(2) rotate(45) translate(5,10)">
  <!-- graphics elements go here -->
</g>

等效于以下功能:

<g transform="translate(-10,-20)">
  <g transform="scale(2)">
    <g transform="rotate(45)">
      <g transform="translate(5,10)">
        <!-- graphics elements go here -->
      </g>
    </g>
  </g>
</g>

2
我知道了,谢谢。但是规范应该明确规定这一点。 - cateyes
2
是的!我发布的内容来自规范。 - Robert Longson
24
规范非常误导人,它不按照提供的顺序应用变换,而是创建一个嵌套的变换结构,在其中最内层的变换首先应用,而这是列表中的最后一个变换。如果规范如此清晰,为什么几乎每个第一次尝试使用SVG的人都会被绊倒呢? - bikeman868
6
同意@bikeman868的观点,从右到左的转换顺序与规范措辞和预期的逻辑行为相反。每次都让我困惑。 - Yarin
6
规范确实按照从左到右的顺序应用变换: transform="A B C"会创建矩阵A、B、C,该顺序是 A * B * C。然而,如果将矩阵视为函数调用,则矩阵乘法最终从右向左“工作”。 - prewett
显示剩余3条评论

0
If you want to sequentially change these transformations 
you have to try this one

<g transform="translate(-10,-20)  onmouseover=changeTransform(evt)">

function changeTransfrom(evt)
{
var id=evt.target;
id.setAttribute('transform',scale(0.5));
id.setAttribute('transform',rotate(30));
id.setAttribute('transform',skewY(45));
id.setAttribute('transform',matrix(2,2));
}

除了缺少引号之外,这种方法不起作用,因为它会覆盖转换属性值。 - Melle
当然!我的意图是给出转换的顺序。 - Chandu D

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接