25

In W3C's spec, it says:

The value of the ‘transform’ attribute is a <transform-list>, which is defined as a list of transform definitions, which are applied in the order provided.

...

If a list of transforms is provided, then the net effect is as if each transform had been specified separately in the order provided

When I tried out the follow markups in firefox, chrome and IE10, all three rendered by doing translate first, then following by rotate! See the codepen snippet. What have I missed here? Or the implementations from the 3 browsers are not W3C compliant?

<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>
Community
  • 1
  • 1
cateyes
  • 5,208
  • 2
  • 24
  • 31
  • 1
    A quick play with your codepen seems to confirm what I'd suspected. The translation is dependant on the rotation angle. Say you start with a car pointing north. If you move it 5m forwards, you'll have moved 5m in a northerly direction. If instead, you rotated your car 45° clock-wise, _then_ drove it 5m forwards, you'd have moved 5m in a north-easterly direction. So you need to do one of two things - (1) reset(apply) if possible the transform matrix to the obj - as one does in 3d content creation programs Blender, Maya, 3dsMax etc. (2) You need to calculate a rotated translation vector. – enhzflep Sep 03 '13 at 06:14

2 Answers2

27

The specification is pretty clear about the order which is that the rightmost transform is applied first.

If a list of transforms is provided, then the net effect is as if each transform had been specified separately in the order provided.

I.e,

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

is functionally equivalent to:

<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>
Robert Longson
  • 118,664
  • 26
  • 252
  • 242
  • 2
    I see, thanks. But the spec should explicitly stipulate this. – cateyes Sep 05 '13 at 02:08
  • 2
    It does! What I've posted is from the spec. – Robert Longson Sep 05 '13 at 07:21
  • 24
    The spec is extremely misleading, it does not apply the transformations in the order provided, instead it creates a nested structure of transformations where the inner most transformation is applied first, and this is the last one in the list. If the spec is so clear, why does this trip up almost everybody who tries SVG for the first time. – bikeman868 Jan 27 '17 at 17:31
  • 6
    Agree with @bikeman868, the right-to-left transform order is the opposite of both the spec wording and the assumed logical behavior. Trips me up every time. – Yarin Nov 27 '17 at 15:21
  • 6
    The spec does apply the transformations in left to right order: transform="A B C" creates matrices A, B, C that get applied A * B * C. However, matrix multiplication ends up "working" from right to left if you view the matrix as a function call. – prewett Dec 18 '18 at 18:11
  • 1
    The specification does follow the logical behavior. That is, this is how matrix transformation works in mathematics. As a consequence, that's also how OpenGL works, how DirectX works, how pretty much all drawing APIs work. This is the assumed logical behavior for anyone who is not fully ignorant of geometry, algebra and graphics. – spectras May 14 '20 at 08:21
  • 2
    In mathematics, the term “applies” is used commonly as function application and the term transform is also commonly used to refer to functions, all of which implies the opposite order than the assumption of matrix multiplication. Having been on a few graphics standards committees, I can easily imagine someone demeaning anyone who didn’t interpret it their way and bullying the committee into accepting ambiguous, if not completely incorrect, language. –  Jul 09 '22 at 23:09
  • The spec does offer a more detailed explanation that helps clear things up: https://www.w3.org/TR/SVG11/coords.html#NestedTransformations – JamesHoux Oct 26 '22 at 04:13
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));
}
Chandu D
  • 505
  • 3
  • 17