为什么当某些样式更新时,透视不会给出相同的结果?



我有两个带有3d变换(rotationY(的盒子。每个人都有几乎相同的价值观,一个观点看起来不错,另一个观点有点错误,但仍然有一些正确的观点。

顶部的第一个盒子没有突出,但它有一个透视图。此外,3°集装箱的大200%

第二个盒子做了一个美丽的3d效果。

在这里,我举了一个我试图解释的例子。

$(".eye").on('click', function () {
$( '.man' ).toggleClass('open');      
})
* {  padding: 0;  margin: 0; }
.eye { padding: 6px 8px; }
.universe {
background: rgb(0 0 255 / 0.3);
position: absolute;
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.dark {
background: rgb(0 255 0 / 0.3);
width: 25%;
height: 25%;
}
.god {
background: rgb(255 0 0 / 0.3);
transform-style: preserve-3d;
transform: perspective(800px);
}
.man {
position: absolute;
transform-origin: top left;
transition: 1s all linear;
} 
.man.open {
transform: rotateY(-60deg); 
}
.life {
background: rgb(255 255 0 / 0.36);
width: 25vw;
height: 25vh;              
}
.no.god {
height: 100%;
}
.no.man {
position: relative; 
}
.yes.god {
height: 200%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="universe">
<div class="dark">
<div class="god">
<div class="man">
<div class="life">Nothing happens until something moves.</div>
</div>
</div>
</div>
<button class="eye"> OPEN </button>
<div class="dark no">
<div class="god no">
<div class="man no">
<div class="life no">Nothing happens until something moves.</div>
</div>
</div>
</div>
<button class="eye"> OPEN </button>
<div class="dark yes">
<div class="god yes">
<div class="man yes">
<div class="life yes">Nothing happens until something moves.</div>
</div>
</div>
</div>
</div>

我认为有些地方出了问题,但不知道为什么。有人能解释一下它为什么会这样吗?

每个都有几乎相同的值,一个透视图看起来很好,

不,它们没有相同的值。一种是使用position:absolute,另一种是position:relative,这产生了很大的差异。如果检查god元素,则在使用创建问题的position:absolute(第一种情况(时会注意到其高度为0。

这里有一个简化的代码来更好地显示您的问题:

.box {
display: inline-block;
vertical-align:top;
width: 100px;
perspective: 200px;
position: relative;
margin: 20px;
background:blue;
}
.box>div {
position: relative;
padding: 10px;
background: red;
color: #fff;
transition: 1s all linear;
transform-origin: top left;
}
body:hover .box > div {
transform: rotateY(-40deg);
}
<div class="box">
<div>Some text here</div>
</div>
<div class="box">
<div style="position:absolute;">Some text here</div>
</div>

为了得到更准确的解释,我们需要参考规范

透视可以通过使Z轴上较高的元素(更靠近观看者(看起来更大,而离得更远的元素看起来更小,来为场景增加深度感。缩放与d/(d − Z)成比例,其中d,即perspective的值,是从绘图平面到观看者眼睛的假定位置的距离。

其次,perspectiveperspective-origin属性可以应用于元素,以影响其三维变换的子元素的渲染,为他们提供一个共享的视角,让他们感觉生活在同一个三维场景中。

然后我们可以看到数学部分:

透视矩阵计算如下:

  1. 从单位矩阵开始。

  2. 通过计算的perspective-origin的X和Y值进行转换

  3. 乘以从perspective()变换函数获得的矩阵,其中长度由透视属性的值提供

  4. 通过perspective-origin的计算X和Y值取反进行转换

技巧在与perspective-origin相关的步骤(1((4(中。如果我们检查定义,我们可以阅读:

perspective-origin的值表示透视原点与参考框左上角的偏移

注意引用框,它是这里的关键,因为这是out情况下的变量(god元素(。如果我们再加上默认值为50% 50%,我们就会得到答案:

<percentage>

水平透视偏移的百分比相对于参照框的宽度。垂直偏移的百分比是相对于参考框的高度的。水平偏移和垂直偏移的值表示与参照框左上角的偏移。


现在我们有了所有的信息来了解正在发生的事情。在元素高度为0的第一种情况下,原点在顶部中心(我们只考虑宽度的50%(,而在第二种情况下原点是中心,因为我们的元素的高度不同于0,更准确地说,高度等于变换元素的高度,这给了我们一个完美的结果。

如果我们改变perspective-origin并考虑像素值,我们将对两者产生相同的结果:

.box {
display: inline-block;
vertical-align:top;
width: 100px;
perspective: 200px;
perspective-origin:50px 30px;
position: relative;
margin: 20px;
background:blue;
}
.box>div {
position: relative;
padding: 10px;
background: red;
color: #fff;
transition: 1s all linear;
transform-origin: top left;
}
body:hover .box > div {
transform: rotateY(-40deg);
}
<div class="box">
<div>Some text here</div>
</div>
<div class="box">
<div style="position:absolute;">Some text here</div>
</div>

总之,perspective-origin的默认值是50% 50%,百分比基于我们应用透视图的元素的大小。现在很明显,如果大小改变,原点将不再相同,这将从逻辑上给我们一个不同的趋势。

为了避免这种情况,我们要么为原点设置像素值,要么考虑直接在相关元素(我们想要变换的元素(上使用perspective(),在这种情况下,我们确信结果是相同的,因为两个元素都是相同的:

.box {
display: inline-block;
vertical-align:top;
width: 100px;
position: relative;
margin: 20px;
background:blue;
}
.box>div {
position: relative;
padding: 10px;
background: red;
color: #fff;
transition: 1s all linear;
transform-origin: center left;
transform: perspective(200px) rotateY(0);
}
body:hover .box > div {
transform: perspective(200px) rotateY(-40deg);
}
<div class="box">
<div>Some text here</div>
</div>
<div class="box">
<div style="position:absolute;">Some text here</div>
</div>
<div class="box" style="height:500px;">
<div style="position:absolute;">Some text here</div>
</div>

在上面应该注意到,perspective-origin是不相关的,transform-origin定义了原点,因为我们使用的是透视图的转换函数版本。

相关问题:

透视和平移Z对角移动

如何在透视模式下计算旋转角度以使宽度适合所需尺寸?

CSS三维转换没有';如果透视设置在属性的末尾,则不起作用

最新更新