为了说明其工作原理,让我们考虑一个动画,以显示缩放效果如何改变旋转。
.red {
width:80px;
height:20px;
background:red;
margin:80px;
transform-origin:left center;
animation: rotate 2s linear infinite;
}
@keyframes rotate {
from{transform:rotate(0)}
to{transform:rotate(360deg)}
}
<div class="container">
<div class="red">
</div>
</div>
正如您在上面看到的,旋转创建了一个完美的圆形。
现在让我们缩放容器并查看差异:
.red {
width:80px;
height:20px;
background:red;
margin:80px;
transform-origin:left center;
animation: rotate 5s linear infinite;
}
@keyframes rotate {
from{transform:rotate(0)}
to{transform:rotate(360deg)}
}
.container {
display:inline-block;
transform:scale(3,1);
transform-origin:left center;
}
<div class="container">
<div class="red">
</div>
</div>
请注意,我们现在不再是圆形,而是椭圆。就像我们取了一个圆并固定了它,这在矩形内创建了偏斜效果。
如果我们做相反的效果,我们先从缩放效果开始,然后应用旋转,则不会有任何倾斜。
.red {
width:80px;
height:20px;
background:red;
margin:80px;
animation: rotate 2s linear infinite;
}
@keyframes rotate {
from{transform:scale(1,1)}
to{transform:scale(3,1)}
}
.container {
display:inline-block;
transform:rotate(30deg);
transform-origin:left center;
}
<div class="container">
<div class="red">
</div>
</div>
用不同的方式来解释:施加旋转将使X和Y轴之间的比率保持相同,因此以后进行缩放时不会看到任何不良影响,但是仅缩放一个轴会破坏该比率,因此,当我们尝试时,我们的形状看起来很糟糕进行旋转。
以下是相关部分:
转换是累积的。也就是说,元素在其父级坐标系内建立其局部坐标系。
从用户的角度来看,元素有效地累积了其祖先的所有变换属性以及应用于该元素的任何局部变换
让我们做一些数学运算,以了解两个转换之间的差异。让我们考虑矩阵乘法和因为我们面对的是一个二维线性变换,我们将做到这一点上?²为简单起见 。
因为scale(2, 1) rotate(10deg)
我们将有
|2 0| |cos(10deg) -sin(10deg)| |2*cos(10deg) -2*sin(10deg) |
|0 1| x |sin(10deg) cos(10deg) | = |1*sin(10deg) 1*cos(10deg) |
现在,如果我们将此矩阵应用于,(Xi,Yi)
我们将获得(Xf,Yf)
如下所示:
Xf = 2* (Xi*cos(10deg) - Yi*sin(10deg))
Yf = Xi*sin(10deg) + Yi*cos(10deg)
请注意,它Xf
是如何具有一个额外的乘数的,这是造成偏斜效果的元凶。就像我们更改了行为或Xf
保留了Yf
现在让我们考虑rotate(10deg) scale(2, 1)
:
|cos(10deg) -sin(10deg)| |2 0| |2*cos(10deg) -1*sin(10deg) |
|sin(10deg) cos(10deg) | x |0 1| = |2*sin(10deg) 1*cos(10deg) |
然后我们将有
Xf = 2*Xi*cos(10deg) - Yi*sin(10deg)
Yf = 2*Xi*sin(10deg) + Yi*cos(10deg)
我们可以将其2*Xi
视为an Xt
,并且可以说我们旋转了(Xt,Yi
)元素,并且此元素最初是考虑X轴缩放的。
CSS还使用仿射变换(例如平移),因此使用?²(笛卡尔坐标)不足以执行我们的计算,因此我们需要考虑??²(同质坐标)。我们之前的计算将是:
|2 0 0| |cos(10deg) -sin(10deg) 0| |2*cos(10deg) -2*sin(10deg) 0|
|0 1 0| x |sin(10deg) cos(10deg) 0| = |1*sin(10deg) 1*cos(10deg) 0|
|0 0 1| |0 0 1| |0 0 1|
在这种情况下,什么都不会改变,因为仿射部分为 空, 但是如果我们将翻译与其他转换结合在一起(例如:),scale(2, 1) translate(10px,20px)
我们将具有以下优势:
|2 0 0| |1 0 10px| |2 0 20px|
|0 1 0| x |0 1 20px| = |0 1 20px|
|0 0 1| |0 0 1 | |0 0 1 |
和
Xf = 2*Xi + 20px;
Yf = Yi + 20px;
1 = 1 (to complete the multiplication)