当 transform 改变 1px 时,元素向上移动了100%。

9
我是一名有用的助手,可以为您进行文本翻译。以下是需要翻译的内容:

我正在我的项目中使用css 3d变换。我试图在多个其他元素的包含元素上应用新的变换。我还尝试在其中一个子元素上使用getBoundingClientRect。该容器还有其他元素。当容器具有以下值时, transform css属性:

translateZ(1026px) rotateX(-90deg) rotateY(180deg) translateZ(439.001px)

这是特定子元素的element.getBoundingClientRect().top值:根据Chrome开发者工具,为77.953109741210944,但当我使用elements选项卡将`transform`属性更改为以下内容时:
translateZ(1027px) rotateX(-90deg) rotateY(180deg) translateZ(439.001px)

这是element.getBoundingClientRect().top的含义:-75048.6484375。可能会导致这种情况的原因是什么?即使我通过控制台修改值,这种情况仍然发生,所以我没有发布任何代码。当我将第一个translateZ设置为1000px时,它仍然大约为77。即使它在0时,边界矩形的顶部也在50-100左右。但是当它超过1026px时,该元素似乎会跳到顶部-80000左右。然而,从视觉上看,该元素看起来应该是正常的,并且不会在1027px处随机“跳动”。有人能说出可能导致这种情况的情况吗?
如果这是浏览器错误或其他问题,我使用的是chrome 32.0.1687.2 dev-m Aura。
编辑:
这是一个jsfiddle链接:

http://jsfiddle.net/a6KxQ/2/

它将生成一个包含所有translateZ值和相应的elt.getBoundingClientRect().top值的表格。代码有点乱,但是在输出的表格中,仔细查看,您会发现,在某个时刻,顶部值会突然跳得很远。然后它会迅速恢复到之前的值。很奇怪。
这个示例可能需要很长时间才能加载。

你能在 jsFiddle 上演示一下吗?这样我们可以更好地观看和测试它。 - jfriend00
我不确定,我的应用程序非常复杂,其他因素可能会影响它,但我想我可以尝试。 - markasoftware
我尝试制作一个JSFiddle,但它按预期正常工作,没有显示问题。 - markasoftware
那么,问题可能与您在 jsFiddle 中缺少的某些内容有关,这对我们而言将会非常困难。我认为您需要着手确定环境中其他引起问题的因素。也许您可以逐渐添加更多内容到您的 jsFiddle 或诊断您代码中可能影响它的其他原因。 - jfriend00
我查看了MDN关于getBoundingClientRect().top的文档,它说:“矩形框顶部相对于视口原点的Y坐标。” 视口原点有可能被移动了吗? - jfriend00
显示剩余11条评论
2个回答

8
正如你所怀疑的那样,这与视角的 perspective 有关。通过增加第一个 translateZ 的值,您将矩形带近了你的位置。最终,它很接近,已经超过了相机的点。从那时起,未旋转的形状就在你的眼后。
然后您进行了 rotateX(-90deg)。发生的事情是矩形向前倾斜(朝着正 Z 方向,但在相机的背后)。现在,由于视图的隧道呈梯形形状,因此您可以看到屏幕截图中所看到的内容。

enter image description here

当相机后面有矩形时,随着旋转,部分矩形会被倾斜回到视野中。

因此,getBoundingClientRect() 实际上给出的是形状边界的底部!现在形状已经翻转了,它不理解 3D。

我希望你能明白我的意思。我想先向您提出问题 :) 在投票之前问我,我可以详细解释。

所以,这是设计上的问题。您可能希望将 translateZ 值限制为小于 perspective。

编辑:

抱歉我一直很忙。我打算给一个更详细的回答。感谢给我悬赏的人。

一个更新的演示

尝试改变数字,您会做出以下观察:

  1. translateZ = perspective - 150px 时,边界框异常地小且位置错误。

  2. perspective - 150px < translateZ < perspective + 150px 时,边界框在其本应该的位置的相反侧,大小异常大。

  3. tranlateZ = perspective + 150px 时,在情况1)中,边界框再次异常地小且位置更高。

  4. 上述情况不受透视点影响。

  5. 150px 是正方形宽度/高度的一半。

  6. tranlateZ > perspective + 150px 时,边界框恢复正常!

为什么会这样呢?

  • 情况1)其中一条边与相机/透视所在的平面相交。
  • 情况2)正方形与相机平面相交
  • 情况3)与情况1中的边相反的边现在与相机/透视平面相交。
  • 情况6)整个正方形都经过了相机平面

用于将3D坐标转换为屏幕上的2D坐标的投影算法没有考虑到两个角落在相机前面,另外两个角落在后面的事实,因此创建了错误的投影,从而导致错误的大小。

这就是我所说的“它不理解3D”的意思。我意识到那很模糊,抱歉。当所有形状都通过相机平面时,它再次起作用。

Firefox和Chrome都有这个问题,但具有不同的数值表示。可能是因为使用了不同的投影矩阵。所以我不想弄清楚到底出了什么问题。向他们发一个错误报告:)

但实际上,你可能需要绕过它。


好的,这个问题可能已经有解决方案了,但我并不完全理解你所说的很多东西。例如,你所说的“视图隧道”是什么意思,为什么它是梯形的?你所说的“因此,getBoundingClientRect()实际上给出的是形状边界的底部!”是什么意思?你所说的“形状边界的底部”是什么意思?为什么会出现问题?即使它在相机后面,如果它的一部分重新进入视野,它不应该仍然正常工作吗?为什么“现在形状翻转后就不能理解3D了”? - markasoftware
好的,我想要一个关于这个是如何工作的解释,但即使你没有提供,我也会给你奖励。 - markasoftware
@Markasoftware,请看一下我制作的演示:演示链接。旋转后的BoundingClientRect值在translateZ = 399px时是正确的。在400px处以非常有趣的方式出现错误,401px及以上则会出现错误。由于透视原点被改变,所以数学计算比较复杂,但问题显然出在透视上。您可以通过限制translateZ的值来避免错误。现在已经很晚了,我会尽快写更多内容。 - Viele
抱歉,但您并没有真正解释为什么边界矩形会偏移。它不能是“不再理解3D”,因为它仍然在正确的位置渲染。赏金要求明确表示:“我不想用“hacky”的方法来修复这个问题”,到目前为止,这并不符合要求。它提供了一个不太合理的解释,并且它所说的只是保持translateZ小于透视。但我的应用程序需要translateZ大于透视。这就是它应该工作的方式。所以很抱歉,如果没有修改,这个答案将无法获得赏金。 - markasoftware
好的,最终决定再次查看并确保我能够正确理解它...我想我明白了。所以基本上,它不喜欢部分可见的形状,因此在这些情况下它不知道该怎么做。虽然这有点解释了发生了什么,但你的答案并没有真正提供任何解决方案,所以我还不打算接受它。 - markasoftware
嘿@Markasoftware,好久不见了。我仍然建议你使用原始答案中的演示。它将帮助您找到错误发生的确切条件。据我所记,这是一个与获取3D对象的2D项目大小有关的数学问题。 3D对象的原始下边缘现在比其原始上边缘更高。但是getBoundingClientRect仍然尝试获取上边缘和下边缘之间的差异。很抱歉我没有解决方案,除了检查您要做什么,并可能找到另一种计算框大小的方法。 - Viele

0

我不确定如何解释它,可能有些偏离主题,但是当您注释掉 perspective CSS 时,整个表格的值都会相同。我不确定 perspective 对数学计算有什么影响...

#main3DWrapper{
  /*
  -webkit-perspective: 1500px;
  -moz-perspective: 1500px;
  perspective:1500px;
  -webkit-perspective-origin: 50% 1%;
  perspective-origin:50% 1%;
  */
  -webkit-transform: translate3d(0,0,0,0);
  transform:translate3d(0,0,0,0);
  display: block;
  height: 100%;
  left: -121.96603393554688px;
  position: absolute;
  top: 409.5150146484375px;
  width: 100%;
}

此外,为什么你在 JavaScript 代码中设置两次 translateZ() 值?
container.style.webkitTransform='translateZ('+dist+'px) rotateX(-90deg) rotateY(180deg) translateZ(429.001px)';
container.style.transform='translateZ('+dist+'px) rotateX(-90deg) rotateY(180deg) translateZ(429.001px)';

难道不应该是这样吗?

container.style.webkitTransform='translateZ('+dist+'px) rotateX(-90deg) rotateY(180deg)';
container.style.transform='translateZ('+dist+'px) rotateX(-90deg) rotateY(180deg)';

这不是我要找的答案。首先,在CSS 3D变换中,大多数事情都需要“perspective”(透视)。要制作3D效果,您需要“perspective”。此外,我还想使用“perspective-origin”来获得正确的视角。是的,它会对数学产生影响,但这是有意为之的。其次,我希望表格中的值发生变化,但我希望它们保持增加而不是随机下降。最后,我使用了两个“translateZ”,因为在旋转后进行平移会使其沿不同方向平移,即使它仍然显示为“Z”。总之,这个答案漏掉了很多内容。 - markasoftware

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接