深入skew()函数

时间:2018-08-30 01:17:13

标签: html css css3 css-transforms skew

我真的需要了解skew(xdeg)函数的工作原理,所有研究似乎都无法解释x角如何影响其他点并使它失真,我需要知道它是否存在任何数学公式或一种方法才能期望使用特定学位的结果。

ps。我已经读过许多文档,其中最好的一个是 DevDocs ,其中说

  

此变换是使变形的剪切映射(对流)   元素内的每个点在水平方向上以一定角度   垂直方向。每个点的坐标都用   值与指定角度成比例,并且与   起源;因此,离原点越远,意愿越强   是它的价值所在。

但是对于给定角度将如何影响元素中的那些点,没有进一步的解释。

在SVG书中,它通过说按特定值推动水平或垂直线来解释偏斜,但是我不知道如何将deg值转换为偏移量

2 个答案:

答案 0 :(得分:4)

要了解skew的工作原理,我们将它与另一个使用角度的变换进行比较。

这是一个旋转示例,我们将变换原点设为top left,然后从此处旋转45deg

.box {
  margin:50px;
  width:200px;
  height:200px;
  background:blue;
}
.box > div {
  height:100%;
  width:100%;
  background:rgba(255,0,0,0.5);
  transform-origin:top left;
  transform:rotate(45deg);
}
<div class="box">
  <div></div>
</div>

在此示例中,找到角度及其工作方式很简单:

enter image description here

现在让我们以相同的示例为例,并将旋转后的元素的高度减小到较小的值:

.box {
  margin:50px;
  width:200px;
  height:200px;
  background:blue;
}
.box > div {
  height:3px;
  width:100%;
  background:red;
  transform-origin:top left;
  transform:rotate(45deg);
}
<div class="box">
  <div></div>
</div>

就像我们有一条旋转的线。现在让我们用倾斜替换rotate:

.box {
  margin:50px;
  width:200px;
  height:200px;
  background:blue;
}
.box > div {
  height:3px;
  width:100%;
  background:red;
  transform-origin:top left;
  transform:skewY(45deg);
}
<div class="box">
  <div></div>
</div>

如果我们将两个结果进行比较,我们会注意到在两种情况下我们都有某种程度的旋转,但是在偏斜变换方面却有不同的大小:

enter image description here

现在更清楚倾斜如何与角度一起工作。变换是一种变形,它依赖于角度来定义此变形。这是一个更好的例子:

enter image description here

蓝色是我们的初始元素,十字是变换的原点,黄色是角度。如果进行旋转,则会获得红线,其中宽度保持不变。如果偏斜,我们将获得橙色线,其中宽度将发生变化,并考虑到插图,其将等于W / cos(angle),其中W是我们的初始宽度(在我们的前一种情况cos(45deg) = 1 / sqrt(2),因此我们将有W * sqrt(2))。


现在我们的初始正方形如何,它的倾斜行为如何?

.box {
  margin:50px;
  width:200px;
  height:200px;
  background:blue;
}
.box > div {
  height:100%;
  width:100%;
  background:red;
  transform-origin:top left;
  transform:skewY(45deg);
}
<div class="box">
  <div></div>
</div>

它的行为与我们之前逐行所述的行为完全相同。如果在另一个方向上应用偏斜,我们也会得到相同的结果:

.box {
  margin:50px;
  width:200px;
  height:200px;
  background:blue;
}
.box > div {
  height:100%;
  width:100%;
  background:red;
  transform-origin:top left;
  transform:skewX(45deg);
}
<div class="box">
  <div></div>
</div>

应用相同的逻辑,但对垂直线并考虑高度。附带说明,skewX(V)skew(V) ref 相同。

现在,如果我们在两个方向上都应用偏斜:

.box {
  margin:50px;
  width:200px;
  height:200px;
  background:blue;
}
.box > div {
  height:100%;
  width:100%;
  background:red;
  transform-origin:top left;
  transform:skew(45deg,10deg);
}
<div class="box">
  <div></div>
</div>

就像我们先应用skewX扭曲垂直线,然后将skewY应用到新形状以扭曲水平线(或相反)一样。这是一个动画,说明skew(45deg,45deg)的神奇效果:

.box {
  margin:50px;
  width:200px;
  height:200px;
  background:blue;
}
.box > div {
  height:100%;
  width:100%;
  background:red;
  transform-origin:top left;
  transform:skew(45deg,10deg);
  animation:change 5s infinite alternate linear;
}
@keyframes change {
  from {
    transform:skew(0deg,0deg);
  }
  50% {
    transform:skew(45deg,0deg);
  }
  to {
    transform:skew(45deg,45deg);
  }
}
<div class="box">
  <div></div>
</div>

那起源呢?转换不会改变,只有引用会改变。换句话说,固定点将移动:

.box {
  margin:50px;
  width:200px;
  height:200px;
  background:blue;
}
.box > div {
  height:100%;
  width:100%;
  background:red;
  transform-origin:center;
  transform:skew(45deg,10deg);
  animation:change 5s infinite alternate linear;
}
@keyframes change {
  from {
    transform:skew(0deg,0deg);
  }
  50% {
    transform:skew(45deg,0deg);
  }
  to {
    transform:skew(45deg,45deg);
  }
}
<div class="box">
  <div></div>
</div>

我们还可能注意到,如果我们朝一个方向倾斜,则只会考虑transform-origin的一个参数。

因此,对于skewXtransform-origin: X Y的值将与X相同。以此方式解释了逐行转换,因为当我们在线时,我们具有一个维度。

.box {
  margin:50px;
  width:200px;
  height:200px;
  background:blue;
}
.box > div {
  height:100%;
  width:100%;
  background:red;
  transform:skewX(45deg);
  animation:change 5s infinite alternate linear;
}
@keyframes change {
  from {
    transform-origin:0 0;
  }
  50% {
    transform-origin:100% 0;/*nothing will happen between 0 and 50%*/
  }
  to {
    transform-origin:100% 100%;
  }
}
<div class="box">
  <div></div>
</div>

更深入

现在,让我们考虑一下矩阵计算,以了解其用法以及tan(angle)的用法。

如果我们引用the documentation,则有:

enter image description here

此矩阵用于基于初始元素的点对点定义变换后的元素的坐标。考虑到这个定义,我们将拥有这些方程式

Xf = Xi + Yi * tan(ax)
Yf = Xi * tan(ay) + Yi

如果仅考虑skewY,显然ax将是0,因此tan(0)将是0,而X不会改变第一个例子就是这种情况,我们在Y轴上只有失真(如果仅应用skewY,则逻辑相同)。

现在,为什么我们有Yf = Xi * tan(ay) + Yi

让我们重新看一下上图:

enter image description here

绿点是Xi,Yi定义的起始点,红点是Xf,Yf定义的转换点。 Xf=Xi和两点之间的距离为Yf-Yi是很简单的。

考虑到插图,我们可以清楚地说tan(ay) = (Yf-Yi)/Xi = (Yf-Yi)/Xf,因此我们将拥有:

Xf = Xi 
Yf = Xi * tan(ay) + Yi

如果我们在另一个方向上有偏斜,我们将应用相同的逻辑。

答案 1 :(得分:2)

应用于<angle>的{​​{3}}就是tan(<angle>)。然后将其插入到转换矩阵中。

好的,关于skew并没有深入,也不是为什么使用角度而不是数字因素才有意义。因此,让我们以下面的ASCII示例显示仅x的偏斜。

   skewX(0)            skewX(45deg)
_|         |_         _|         |_ => original box markers
  a o o o o         a o o o o    
  b o o o o           b o o o o
  c o x o o             c o x o o   <-- this line didn't move
  d o o o o               d o o o o
  e o o o z                 e o o o z
 |         |           |         |

因此,如果我们应用tan(45deg),则它的skewX因子为1。
这意味着所有水平线都将偏移距转换原点的距离的1倍。

在上面的示例中,变换原点是5 * 5 图像的中心(x)。
因此,第一条像素线(a o o o o)与原点之间的距离为负两个像素,它将在左侧平移2px。
最后一行(e o o o z)距原点+ 2px,它将在右边翻译2px。
位于原点的中间线(c o x o o)不受此变换的影响。

好的,但这仍然不能解释为什么要麻烦角度而不是因素...

角度表示法也很有意义,因为当我们将每列的中心点作为锚点旋转45度时,我们也可以解释这个例子。

即使只是我的推测,角度也具有允许skewN(90deg)状态(无法用数字因子表示)的附加好处。