未倾斜 child 未对齐

Unskewed child not aligning

注意:这个问题是关于输出的问题,不是关于创建任何形状的问题。


我最近创建了一个形状:

.prog {
    position: relative;
    top: 20px;
    width: 150px;
    height: 120px;
    background: green;
    display: inline-block;
    transform: skewY(20deg);
    transform-origin: 0% 100%;
    transition: 0.8s ease;
}
.prog:before {
    content: "";
    position: absolute;
    left: 150px;
    width: 150px;
    height: 120px;
    background: red;
    transform: skewY(-40deg);
    transform-origin: 0% 100%;
    transition: 0.8s ease;
}
<div class="prog "></div>

在上面的代码片段中,绿色形状是 .prog 元素,并且是倾斜的。红色形状是第一个元素的 :before 伪元素。

我将 .prog (skewY) 倾斜到 20 度。现在,我需要 :before 为 -20 度。为此,我首先不得不取消它。然后再倾斜 20 度。
所以最终 skewY 值将是 -40 度。我应用了这个,并适当 transform-origins.

但问题是 两个形状的顶点没有对齐。他们应该,但他们不是。这是一张显示问题的图片:

黑线仅供参考

现在更多了!

我歪曲了 -20 -20 而不是 -40 :

transform: skewY(-20deg) skewY(-20deg); <-- 这有效!
transform: skewY(-40deg); <---------------- 这不是!

通过对我最初的答案进行修改,产生输出而不是解释,我会假设*效果被看到是因为您猜测负偏斜可用于抵消正偏斜曲线上的位置,而实际上 - 在负值处您正在负偏斜曲线上操作。

这首先需要偏斜的度量是单一的并且出现在同一条曲线上(见下面的正态曲线),正值和负值允许沿着曲线移动。

但是,负偏斜和正偏斜的曲线是反尾的。

零偏斜是唯一在两者上运行相同的值。因此,如果您有一个元素,对其应用 20 度的偏斜,然后应用负 20 的偏斜,您实际上会有零偏斜(正或负),因此使用负偏移 出现 上班..

但是,如果您随后应用额外的负偏斜,您将得到一个负偏斜的元素,其曲线不同并且不等于正偏斜曲线上的反向等效位置。

20deg = 原始元素,在正偏斜曲线上 20deg

20deg - 20deg = 0,正负偏斜曲线相同

-40deg = 使元素当前 20deg 偏斜,负 40deg = 负偏斜曲线上的 20deg - 不是正偏斜曲线上的等效 'opposite' 点

当使用 psuedos 时,偏斜有效,因为您没有用新的偏斜量抵消正偏斜值。

*我不是数学家,恐怕只能说是猜想

我将只解决主要问题,即为什么会发生,而不是尝试提供替代方案

由于您的数学看起来很准确,我们必须搜索不准确的内容,即平台本身...

MDN's article on transform声明不是稳定技术:

This is an experimental technology
Because this technology's specification has not stabilized, check the

(强调我的)

考虑以下因素:

当你倾斜主要 div 时,它需要大量的浏览器渲染计算才能在 2D 环境中显示考虑到两个 3 轴的外观......伪元素会受到这些计算的影响,如您所见,如果您将它从放置它的边缘向左一点:

根据应用于主要 div 的 Y 偏斜,看到我刚向左移动,这导致它向下移动了一点。现在,当你重新倾斜伪元素时,再加上另一个大量的计算......浏览器将无法提供 3D space 在 2D 环境中的外观的准确渲染......

skew 引入了一个等于角度正切的垂直偏移。因此,skew(20deg) 引入了 tan(20deg) 的偏移量。

为了使您的示例生效,应该是

tan(-20deg) = tan(20deg) + tan( -2 * 20deg)

tan (2 * x) = 2 * tan (x)

但事实并非如此,切线与求和不相关

扭转它所需的偏差是

result = - atan ( 2 * tan (x))

对于 x = 20,给出的结果是

36,052388732387908475278040193987

(大约)

"unskewed" child 的行为是正常的,这是偏斜的工作方式。为了理解这一点,我将把问题简化为:

why isn't skewX(40deg) the same as skewX(20deg) skewX(20deg)?

div {
    width: 100px; height: 100px;
    position:absolute;
    top:20px; left:20px;
    transform-origin: 0 0;
}
.d1 {
    transform: skewX(40deg);
    background: red;
    opacity:0.7;
}
.d2 {
    transform: skewX(20deg) skewX(20deg);
    background: blue;
    opacity:0.7;
}
/** FOR THE DEMO **/
body {background: url('http://i.stack.imgur.com/GySvQ.png');background-size: 10px;}
.m {text-align:right;padding-top:105px;}
.m1{width:83px;color:red;border-right:1px solid red;}
.m2 {width:72px;color:blue;border-right:1px solid blue;}
p{margin:0 0 5px 150px;color:red;}
.b{color:blue;}
<div class="d1"></div>
<div class="d2"></div>
<div class="m m1">x = 83</div>
<div class="m m2"><br/>x = 72</div>
<p class="r">skewX(40deg)</p>
<p class="b">skewX(20deg) skewX(20deg)</p>

注意:为了便于解释,我将使用 100*100 正方形 div 并且变换原点设置在这个 div 的左上角].就像上面的代码片段。


要了解这两种转换之间的区别,我们需要探索 CSS skew() 函数的工作方式。 The specs 说:

A 2D skew transformation along the X axis with the parameter alpha is equivalent to the matrix:

所以这意味着我们可以像这样计算 2D X 倾斜元素的每个点的坐标:

| 1 tan(α) | . | x |
| 0   1    |   | y |
  • α为X偏角
  • x/y变换前点的坐标

对于 skewX(40deg)

α = tan(40deg) ~= 0.83

| 1  0.83 | . | 0   |   | 83  |
| 0  1    |   | 100 | = | 100 |

如代码片段示例中所示,新坐标为 x = 83


对于 skewX(20deg) skewX(20deg)

α = tan(20deg) ~= 0.36

第一次倾斜:

| 1  0.36 | . | 0   |   | 36  |
| 0  1    |   | 100 | = | 100 |

第二次倾斜:

| 1  0.36 | . | 36  |   | 72  |
| 0  1    |   | 100 | = | 100 |

如代码片段所示,新坐标为 x = 72


结论

两种转换都不会给出相同的结果。所以 skewY(20deg) skewY(-40deg)skewY(-20deg) 的变换不同,红色和绿色元素的两个顶角不能对齐:

tan(20deg) != tan(40deg)/2 

参考资料: