为什么在更新某些样式时透视图不能给出相同的结果? [英] Why perspective isn't giving the same result when some styles are updated?

查看:47
本文介绍了为什么在更新某些样式时透视图不能给出相同的结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个具有3d转换(rotationY)的框.每个都有几乎相同的值,一个角度看起来不错,另一个角度有点错误,但仍然有一些正确的角度.

I have two boxes with 3d transformation (rotationY). Each have almost the same values, one perspective looks fine, the other kinda wrong but still have some correct perspective.

顶部的第一个框没有突出,但是它具有透视图.另外,容器的3度角大了200%

The first box at the top side does not protrude, but it have a perspective view yet. Also the 3° the container is 200% bigger

第二个框具有精美的3d效果.

The second box do a beautiful 3d effect.

我在这里举例说明了我要解释的内容.

Here I made the example of what I'm trying to explain.

$(".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>

我认为有些地方做错了,但无法弄清楚原因.有人可以解释我为什么会这样吗?

I think something is working wrong, but can't figure it out why. Can someone explain me why it's behaving like that?

推荐答案

每个值几乎相同,一个视角看起来很好

Each have almost the same values, one perspective looks fine,

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

No they don't have the same values. One is using position:absolute and the the other one position:relative and this make a big difference. If you inspect the god element you will notice that its height is 0 when using the position:absolute (the first case) which is creating the issue.

以下是简化的代码,可以更好地显示您的问题:

Here is a simplified code to better show your issue:

.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>

要获得更准确的说明,我们需要参考规范

For a more accurate explanation we need to refer to the specification

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

Perspective can be used to add a feeling of depth to a scene by making elements higher on the Z axis (closer to the viewer) appear larger, and those further away to appear smaller. The scaling is proportional to d/(d − Z) where d, the value of perspective, is the distance from the drawing plane to the the assumed position of the viewer’s eye.

第二,可以将 perspective perspective-origin 属性应用于元素,以影响其3D转换后的子代的呈现,从而为它们提供一个共享的视角,从而提供他们住在同一三维场景中的印象.

Second, the perspective and perspective-origin properties can be applied to an element to influence the rendering of its 3d-transformed children, giving them a shared perspective that provides the impression of them living in the same three-dimensional scene.

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

Then we can see the math part:

透视矩阵的计算如下:

The perspective matrix is computed as follows:

  1. 从单位矩阵开始.

  1. Start with the identity matrix.

通过计算的 perspective-origin

乘以将从 perspective()转换函数获得的矩阵,其中长度由视角属性的值提供

Multiply by the matrix that would be obtained from the perspective() transform function, where the length is provided by the value of the perspective property

通过求反的 perspective-origin

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

The trick is within the steps (1)(4) related to perspective-origin. If we check the definition we can read:

perspective-origin 的值表示透视图原点相对于参考框左上角的偏移量.

The values for perspective-origin represent an offset of the perspective origin from the top left corner of the reference box.

请注意参考框,这是关键,因为这是out变量( god 元素).如果我们加上默认值是 50%50%的事实,我们将得到答案:

Note the reference box which is the key here because this is the variable in out case (the god element). If we add to this the fact that the default value is 50% 50% we get our answer:

< percentage>

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

A percentage for the horizontal perspective offset is relative to the width of the reference box. A percentage for the vertical offset is relative to height of the reference box. The value for the horizontal and vertical offset represent an offset from the top left corner of the reference box.


现在,我们拥有所有信息来了解正在发生的事情.在第一种情况下,元素的高度为0,原点位于顶部中心(我们仅考虑宽度的 50%),而在第二种情况下,原点为中心,因为元素具有高度不同于0,更确切地说,高度等于转换后的元素之一的高度,可以为我们带来完美的结果.


Now we have all the information to understand what is happening. In the first case where the element has 0 height, the origin is on the top center (we only consider 50% of the width) while in the second case the origin is the center since our element has a height different from 0 and more precisely a height equal to the one of the transformed element which give us a perfect result.

如果我们更改 perspective-origin ,并且考虑像素值,则两者的结果相同:

If we change the perspective-origin and we consider pixel values we will have the same result for both:

.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%,百分比基于我们应用透视图的元素的大小.现在很明显,如果更改大小,则原点将不再相同,这在逻辑上将为我们提供不同的提示.

To conclude, the default value of perspective-origin is 50% 50% and percentage is based on the size of the element where we apply the perspective. It's now clear that if the size is changed the origin will no more be the same which will logically give us a different rendring.

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

To avoid this we either set a pixel value for the origin OR we consider the use of perspective() directly on the concerned element (the one we want to transform) and in this case we are sure the result will be the same since both elements are the same:

.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 定义了原点,因为我们使用的是透视图的变换功能版本.

You should note in the above that perspective-origin is irrelevant and the transform-origin with define the origin since we are using the transform-function version of perspective.

相关问题:

透视并和平移动Z对角线

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

如果在属性的末尾设置了透视图,则CSS 3d转换将不起作用

这篇关于为什么在更新某些样式时透视图不能给出相同的结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆