首页>前端教程>CSS教程

transform中的3D变化,你的眼睛真好骗!

好久没写教程了,这几年忙着上课备课,学习新的框架,忙着新公司的事情,一点空余的时间都榨不出来,结果新公司还是干倒闭了,万事皆空……!

趁着现在没工作,把教程案例整理一下,算是做个总结。也不知道自己前端开发这个方向的职业生涯是否已经结束,毕竟这个就业市场对我们老人太不友好了。

如果我真的转行了,这个网站就是我十多年职业生涯的坟墓,欢迎大家来盗墓,哈哈……

一、3D变换

首先理解我们生活的环境就是三维空间的,有平面,有纵向的高度。

而通过拍照片就是把三维的空间变成了二维的。

3D.png

1、三维空间的特点

1、近大远小

2、近高远低

3、近疏远密

4、近实远虚

5、被遮挡的背面不可见

45925.jpg

1.2 三维坐标系

三维坐标系就是表现立体空间的三个轴向,由x、y、z构成。

三维坐标系.png

x轴:水平向右为正,向左为负值

y轴:垂直向下为正,向上为负值

z轴:垂直屏幕,往外面为正,往里面为负值

1.3 3D旋转

  • rotateX()

  • rotateY()

  • rotateZ()

  • rotate3d(x,y,z,deg) 了解即可

https://developer.mozilla.org/zh-CN/docs/Web/CSS/transform-function/rotate3d

可以把沿着x轴旋转看成是体操单杠

rotatex.gif

沿着y轴旋转看成是蔡依林的钢管舞

rotateY.gif

旋转飞刀的特技表演是沿着z轴旋转

feidao.jpg

1.4 3D移动

  • translateX()  沿着x轴移动

  • translateY()  沿着y轴移动

  • translateZ()  沿着z轴移动 ,不能是百分比的值。

  • translate3d(x,y,z)   不能省略x、y、z的值,可以设置为0

发现普通的2D变换写法,translateZ没有效果,这是为什么呢?

我们需要了解透视的原理。

1.4 透视perspective

perspective属性的存在与否决定了你所看到的是2次元的还是3次元的,也就是是2D transform还是3D transform. 这不难理解,没有透视,不成3D.

学过一点点美术的人应该都听过一点透视:

toushi.png

9700.jpg

两条平行线在透视里也有相交的那一天!

CSS3 3D transform的透视点默认是在浏览器的前方!

显示器中3D效果元素的透视点在显示器的前方(不是后面),近似就是我们眼睛所在方位!

视距.png

perspective透视能给舞台(scene,变换元素所处的空间)添加纵深感,结果就是元素距离观看者越近就表现得越大,越远就表现得越小(通过变换可以改变元素在Z轴上的位置)。

perspective属性指定观看者的眼睛(假设的)与屏幕 (drawing plane)之间的距离。如果将perspective属性的值设为d,则元素的缩放比例就等于d/(d − z),z是元素在Z轴上的位置,更准确的说是变换前元素所在的与Z轴垂直的平面在Z轴上的坐标位置。

把物体通过translateZ移动到距离眼睛越近,在屏幕上形成的成像面积越大。

d:是视距的大小,也就是perspective的值,需要在被观察的物体的父元素上设置

z:是物体移动的translateZ的值

元素的缩放比例: d / (d - z)

perspective属性

可取值:none | <length>

<length>只能为正值,是观看者与z=0平面的距离,使具有3D变换的元素产生透视效果(当值为0或负值时,无透视效果,变换元素表现为扁平化)。

值为none时,无透视效果,元素在画布上扁平化呈现。

perspective属性值不为none的元素,创建一个层叠上下文和一个包含块(规范上说和相对定位有点类似,和transform很像)。

1.5 perspective-origin

该属性设置了观看者的眼睛在舞台元素上的投影位置.

p-origin.png

可取值:<percentage> | <length> | 关键字

默认值为:50% 50%

第一个值表示与border box左边界的距离,第二个值表示与border box上边界的距离。当只指定一个值时,第二个值作为50%处理。

<percentage>相对于舞台元素的border box的尺寸计算。

x-position

  • <percentage> 百分比,相对于元素宽度,可为负值。

  • <length> 长度值,可为负值。

  • left,关键字,0值的简记。

  • center,关键字,50%的简记。

  • right,关键字,100%的简记。

y-position

  • <percentage> 百分比,相对于元素的高度,可为负值。

  • <length> 长度值,可为负值。

  • top,关键字,0值得简记。

  • center,关键字,50%的简记。

  • bottom,关键字,100%的简记。

1.6 3D渲染上下文

一个3D渲染上下文本质上是一个三维坐标系,这个三维坐标系由一组具有共同祖先(舞台元素)并且进行3D变换的元素共享。

在3D渲染上下文中的元素在渲染时层次关系由他们在Z轴上的位置决定。如果3D变换使他们相互交叉,那么在渲染时就让他们交叉着渲染。

首先transform-style属性值为flat的元素创建一个3D渲染上下文,把这个元素称为祖先元素(舞台元素)。

默认情况下,perspective属性值不为none的元素是扁平的(flattening),因此它创建一个3D渲染上下文。

其次,如果后代元素的transform-style属性值为auto或preserve-3d,则该后代元素将其所处的3D渲染上下文(enclosing 3D rendering context)共享给它包含的后代元素。

把transform-style属性的值设置为preserve-3d可以让这个透视元素(perspective element)扩展包含他的3D渲染上下文的范围至他的后代元素。

再次,如果一个后代元素的transform-style属性值为flat,它虽然参与到包含他的父3D渲染上下文(containing 3D rendering context)中,但是同时对于它包含的后代元素,它也创建一个新的3D渲染上下文。不过,对于这个新创建的3D渲染上下文,在渲染时不是作为一个三维空间渲染,而是作为一个平面渲染。

注意:3D渲染上下文的概念类似于层叠上下文的概念。一个有明确z-index值的定位元素自身创建一个层叠上下文,但是他还是参与到他所处的祖先元素创建的层叠上下文中。相似地,一个元素能为他的后代元素创建一个3D渲染上下文,但是他自身还是参与到他的祖先元素创建的3D渲染上下文中。就像元素在层叠上下文中按照z-index属性决定的层次渲染一样,元素在3D渲染上下文中按照z-depth顺序渲染而且可以互相交叉。

一些CSS属性值使一个元素及其后代元素在渲染时作为一个整体渲染。本质上这些CSS属性值强制将元素的transform-style属性的值重设为flat,这些元素被称为扁平元素(flattening elements)。所以这些元素都会创建一个新的3D渲染上下文。根元素的transform-style属性的值为flat。

1.7  transform-style

该属性要在父元素上设置,对该父元素的子元素(或者说后代元素)起作用。

transform-style:flat ;  子元素不开启3d立体空间,默认值

transform-style:preserve-3d ;  子元素开启立体空间,看起来和父元素处于同一个立体空间中。

transform-style的可取值为:auto  |  flat | preserve-3d

默认值为 auto,不可继承。

当transform-style的值为“flat”时,元素创建一个层叠上下文(stacking context)和一个3D渲染上下文(3D rendering context)。

transform-style属性值为“auto”的元素在计算3D渲染上下文时会被忽略。

transform-style属性值为“preserve-3d”的元素会扩大其所处的3D渲染上下文的范围,即使transform 或 preserve属性的值会导致扁平化。同时,transform-style属性值为“preserve-3d”的元素会创建一个层叠上下文和一个包含块。

以下CSS属性值会导致后代元素(descendant elements)扁平化显示,也就是说强制父元素transform-style属性的值转变为“flat”:

  • overflow: 除了 visible的其它值.

  • opacity: 小于1的值.

  • filter: 除了none的值.

以下CSS属性值会使transform-style的默认值重设为flat:

  • transform: 除了none的值.

  • perspective: 除了none的值

总结:perspective属性可以为3D变换上下文中的后代变换元素提供一个共同的透视变换矩阵,从而被用来确保这些3D变换元素好像处在同一个有深度的三维空间中。把transform-style属性的值设置为preserve-3d,可以让这个透视元素扩展包含他的3D渲染上下文的范围至他的后代元素。

1.8 Backface Visibility 背面可见性

backface-visibility属性

可取值:visible | hidden

默认值:visible

该属性对2D变换无效。

visible 表示背面可见,允许显示正面的镜像。

hidden 表示背面不可见。

利用三维变换,使看到变换元素的背面成为可能。在背面可见的情况下,不管是哪一面,3D变换元素都显示同样的内容,背面内容是前面内容的镜像(就好像元素被投影到一面镜子上)。默认情况下,当元素的背面朝向观看者时,观看者可以看到这个背面的内容。事实上,当元素的背面朝向观看者时,开发者可以通过backface-visibility属性,让该元素的内容不可见。

如果一个动画元素的backface-visibility属性的值为hidden,那么他的内容是交替可见的。只有当他的前面朝向观看者时,他的内容才是可见的。

我们可以自己设置前面和背面的内容。

比如经典的翻转案例,点击图片看效果,通过拖动进度条可以看到图片被翻转成另一张图片了。

3.jpg

1.9 transform-origin

改变元素的中心点的位置。

默认是以元素的中心点进行缩放,可以利用transform-origin属性修改中心点,定位和background-position的用法一样。

left center right

top center bottom

%

length

总结

要实现3D变换,要用到下面几个属性:

属性
描述CSS版本
transform向元素应用 2D 或 3D 转换。3
transform-origin设置变换基点(局部坐标系原点)的位置。3
transform-style规定被嵌套元素如何在 3D 空间中显示。3
perspective规定 3D 元素的透视效果。3
perspective-origin规定观看者眼睛的投影位置。3
backface-visibility定义元素内容在不面对屏幕时是否可见。3

2、案例

举一个旋转木马的例子吧,这个比较常见。

点击图片看效果。

4.jpg

核心代码如下:

        .banner{
            width: 200px;
            height: 200px;
            margin: 300px auto;
            perspective: 500px;
            perspective-origin: bottom center;
        }
        .list{
            transition: 10s;
            transform-style: preserve-3d;
            position: relative;
            height: 200px;
            animation: rotate 10s linear infinite;
        }
        .list:hover {
            animation-play-state: paused;
        }
        .item{
            position: absolute;
        }
        .item:nth-child(2){
            transform:rotateY(0deg) translateZ(200px);
        }
        .item:nth-child(3){
            transform:rotateY(60deg) translateZ(200px);
        }
        .item:nth-child(4){
            transform:rotateY(120deg) translateZ(200px);
        }
        .item:nth-child(5){
            transform:rotateY(180deg) translateZ(200px);
        }
        .item:nth-child(6){
            transform:rotateY(240deg) translateZ(200px);
        }
        .item:nth-child(7){
            transform:rotateY(300deg) translateZ(200px);
        }
        /* .list:hover{
            transform: rotateY(-360deg);
        } */
        @keyframes rotate {
            to {
                transform: rotateY(-360deg);
            }
        }

当然这种常见的转圈圈的图片效果也没问题了。点击看看吧。

5.jpg

还有经典的正方体也举一反三了。

6.jpg

点赞


4
保存到:

相关文章

发表评论:

◎请发表你卖萌撒娇或一针见血的评论,严禁小广告。

Top