Reputation: 11389
All:
When I try CSS transform, something about the order of scale and translate confused me:
<svg>
<rect x="10" y="10" width="20" height="30" style="stroke: #3333cc; fill:none;"/>
<rect x="0" y="0" width="20" height="30" style="stroke: #000000; fill:none;" transform="scale(2) translate(10, 10)"/>
</svg>
<svg>
<rect x="10" y="10" width="20" height="30" style="stroke: #3333cc; fill:none;"/>
<rect x="0" y="0" width="20" height="30" style="stroke: #000000; fill:none;" transform="translate(10, 10) scale(2)"/>
</svg>
These two give different effects. Could anyone give me some explanation about how the CSS transform be processed and rendered?
Thanks
Upvotes: 1
Views: 101
Reputation: 236
Every transform function like scale, translate represents a matrix. And matrix concatenation/multiplication is not commutative. So M1 x M2 must not be equal to M2 x M1.
E.g. a scaling matrix (column major order), scale(2, 2):
m11=2.000 m21=0.000 m31=0.000
m12=0.000 m22=2.000 m32=0.000
m13=0.000 m23=0.000 m33=1.000
E.g. a translation matrix, translate(10, 10):
m11=1.000 m21=0.000 m31=10.000
m12=0.000 m22=1.000 m32=10.000
m13=0.000 m23=0.000 m33=1.000
Scale * Translate:
m11=2.000 m21=0.000 m31=20.000
m12=0.000 m22=2.000 m32=20.000
m13=0.000 m23=0.000 m33=1.000
Translate * Scale:
m11=2.000 m21=0.000 m31=10.000
m12=0.000 m22=2.000 m32=10.000
m13=0.000 m23=0.000 m33=1.000
Upvotes: 1
Reputation: 4797
From W3C
x = "" The x-axis coordinate of the side of the rectangle which has the smaller x-axis coordinate value in the current user coordinate system.
and Mozilla Developer Network:
This attribute indicates an x-axis coordinate in the user coordinate system. The exact effect of this coordinate depend on each element.
The reason they don't look the same is because scaling the element also scaled the user coordinate system.
I've added two more SVG elements so we can see what it looks like with just the first transform applied to it.
<svg>
<rect x="10" y="10" width="20" height="30" style="stroke: #3333cc; fill:none;"/>
<rect x="0" y="0" width="20" height="30" style="stroke: #000000; fill:none;" transform="scale(2)"/>
</svg>
<svg>
<rect x="10" y="10" width="20" height="30" style="stroke: #3333cc; fill:none;"/>
<rect x="0" y="0" width="20" height="30" style="stroke: #000000; fill:none;" transform="scale(2) translate(10, 10)"/>
</svg>
<svg>
<rect x="10" y="10" width="20" height="30" style="stroke: #3333cc; fill:none;"/>
<rect x="0" y="0" width="20" height="30" style="stroke: #000000; fill:none;" transform="translate(10, 10)"/>
</svg>
<svg>
<rect x="10" y="10" width="20" height="30" style="stroke: #3333cc; fill:none;"/>
<rect x="0" y="0" width="20" height="30" style="stroke: #000000; fill:none;" transform="translate(10, 10) scale(2)"/>
</svg>
In the first one the scale is applied first. Now both the rect and the user coordinate system is 2x as big as the purple rect. So when it is moved to 10,10 that is not the same location as it is for the purple rect.
In the second, the rect is moved first. It has the same coordinate system as the purple rect so it ends up in the exact same place. It is then scaled so it's upper left hand corner stays in the same place.
Upvotes: 1