Skip to content

[css-transforms-1] Example 5 is wrong : order is reversed #5520

@mclegrand

Description

@mclegrand

The order of things in example 5 of https://github.com/w3c/csswg-drafts/blob/master/css-transforms-1/Overview.bs#L284 is wrong and contradicts both section 10 and example 2 (which are right), as explained by the following commented file :

(in red : what actually happens "if the div element gets translated by 80px to the bottom left direction, then scaled up by 150% and finally rotated by 45°."; in blue what happens if you just right-add transformations (in particular, you can't get from the translated object to the scaled+translated object with a origin-centered scaling, and you can't get from the translated+scaled one to the final one with a origin-centered rotation )); in green the "natural" mental transformations : take the original object, rotate the result, translate the result

<svg xmlns="http://www.w3.org/2000/svg">

<rect x="40" y="40" width="70" height="70" opacity="0.5"/> <!-- original element -->
<rect x="40" y="40" width="70" height="70" opacity="0.6" fill="green" transform="translate(80,80) scale(1.5) rotate(45)"/> <!-- resulting element -->


<!-- not the correct visual path to the result -->
<rect x="120" y="120" width="70" height="70" opacity="0.5" fill="red"/><!-- translated-->
<rect x="180" y="180" width="105" height="105" opacity="0.5" fill="red"/><!-- translated then scaled -->
<rect x="180" y="180" width="105" height="105" opacity="0.5" transform="rotate(45)" fill="red"/> <!-- translated then scaled then rotated (WRONG RESULT) -->



<!-- not the correct visual path to the result (because of multiplication order) -->
<g transform="translate(80,80)">
  <rect x="40" y="40" width="70" height="70" opacity="0.5" fill="blue"/>
  <g transform="scale(1.5)">
          <rect x="40" y="40" width="70" height="70" opacity="0.5" fill="blue"/> <!-- different from the "translated then scaled" -->
    <g transform="rotate(45)">
            <rect x="40" y="40" width="70" height="70" opacity="0.5" fill="blue"/> <!-- resulting element -->
    </g>
  </g>
</g>

<!-- correct visual/mental path to the result : rotated first (goes to the left of the image because it started on the diagonal), then scale it (stays to the left, lower), then move it diagonally -->
<g transform="rotate(45)">
  <rect x="40" y="40" width="70" height="70" opacity="0.5" fill="green"/>
</g>

<g transform="scale(1.5) rotate(45)">
  <rect x="40" y="40" width="70" height="70" opacity="0.5" fill="green"/>
</g>

</svg>

Hence,

  • the sentence "these transforms get multiplied in the reverse order:" is also wrong (by the way, it's contradicted by the "For more details see the transform function list" : The resulting transform is the matrix multiplication of the list of transforms. (section 10) --which is right--
  • the "post-multiplied" in 1 and 2 should be "pre-multiplied" (as we want trans×scale×rot×point : the example (and the identical hierarchy) is the same as in example 2 which tells to multiply translate, scale, and rot matrices in order )
  • the diagram is very misleading! In particular, if the result of the translation shown as done first is not centered on 0,0, then both the scaling and rotation should move the square away…
  • the identical nesting is right.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions