CSS3 3D transform

目录

一、transform简介

1、定义和用法

2、浏览器支持

3、语法

二、 学习步骤

1、 前情提要

2、 什么是3D transform变换

3、 关键点:rotateX, rotateY, rotateZ

4、 perspective属性

5、translateZ告诉你透视位置

6、perspective-origin

(1)源点向左偏

(2)源点左偏同时上偏

7、transform-style属性

8、backface-visibility

(1)什么是backface-visibility

(2)应用实例

①旋转的甜甜圈

②洒落的咖啡

9、实际应用-CSS 3D开门动画

一、transform简介

1、定义和用法
transform 属性对元素进行2D 或 3D 转换。该属性能让我们对元素进行旋转、缩放、移动或倾斜。

2、浏览器支持
在这里插入图片描述
(图片来源于“菜鸟教程”)

3、语法
transform: none|transform-functions
在这里插入图片描述

(来源:W3School http://www.w3school.com.cn/cssref/pr_transform.asp)

学习步骤

1、前情提要

在这里插入图片描述

这是css3 中的3D坐标系,后面会用的上

2、什么是3D transform变换

CSS3中的3D变换效果,本质上就相当于我们在生活中做各种动作时姿势体态的变换,又称姿态的变换。

举个栗子:

在这里插入图片描述

他们踢足球的过程就相当于在做3D变换!!!

所以,在现实生活中,一切的动作都属于3D变换。

3、关键点:rotateX, rotateY, rotateZ

3D transform中有下面这三个方法:

rotateX( angle )
rotateY( angle )
rotateZ( angle )
这三个是学习和理解3D transform的基础,也是弄懂perspective的突破口

rotateX( angle ):以x轴为转轴旋转

在这里插入图片描述

rotateY( angle ):以y轴为转轴旋转

在这里插入图片描述

rotateZ( angle ):以z轴为转轴旋转

在这里插入图片描述

还不懂?!举个栗子就知道了

在这里插入图片描述

郭伟阳在体操比赛中的运动是:rotateX

在这里插入图片描述

蔡依林的钢管舞是:rotateY

在这里插入图片描述

这个运动员的运动就是:rotateZ

4、perspective属性

perspective的中文意思是:透视,视角!

在这里插入图片描述

perspective:400px;

电脑显示屏是一个2D平面,图像之所以具有立体感(3D效果),其实只是一种视觉呈现,通过透视可以实现此目的。

透视可以将一个2D平面,在转换的过程当中,呈现3D效果。
在这里插入图片描述

CSS3 3D transform的透视点是在浏览器的前方,相当于我们眼睛的位置

注:并非任何情况下需要透视效果,根据开发需要进行设置。

先来看看perspective的作用:

CSS代码:

  .box{

            border:solid 1px #000;

            box-sizing:content-box;

            margin:100px auto;

            width:1000px;

            height:300px;

            /* 重点看这里 */

            perspective:800px;

        }

        .child{

            box-sizing:content-box;

            width:300px;

            height:300px;

            float:left;

            margin-left:5px;

            background-color:#87D30A;

            /* 重点看这里 */

            transform:rotateY(95deg);

        }

HTML代码:

<div class="box">

        <div class="child"></div>

        <div class="child"></div>

        <div class="child"></div>

        <div style="clear:both;"></div>

    </div>

在这里插入图片描述

从这个demo看box父元素上有perspective,child子元素Y轴旋转95度。从效果看可以想象这三个div的透视可以有一个交点,且这个交点看起来在第二个div附近。

接着,尝试不断调整perspective的值,从原来的800px调整到4000px,也就是原来的5倍。其他属性不变,看看效果。

在这里插入图片描述

调整了perspective后你会发现div旋转幅度变大了,且透视焦点转移到了第一个div附近。通过这个调整发现,改变perspective的值透视焦点会发生改变。

在这里插入图片描述

这就是3D世界的坐标图。而perspective在Z轴上,而perspective是设置Z轴的长度。在css3中只有设置了perspective的值元素才会有Z轴,perspective为none元素则没有Z轴(就是2D元素)。

5、translateZ告诉你透视位置
我们都知道近大远小的道理,对于没有rotateX以及rotateY的元素,translateZ的功能就是让元素在自己的眼前或近或远。

举个栗子:

我们设置元素perspective为201像素,如下:

perspective: 201px;

则其子元素,设置的translateZ值越小,则子元素大小越小(因为元素远去,我们眼睛看到的就会变小);

translateZ值越大,该元素也会越来越大,当translateZ值非常接近201像素,但是不超过201像素的时候(如200像素),该元素的大小就会撑满整个屏幕(如果父辈元素没有类似overflow:hidden的限制的话)。

因为这个时候,子元素正好移到了你的眼睛前面,所谓“一叶蔽目,不见泰山”,就是这么回事。当translateZ值再变大,超过201像素的时候,该元素看不见了——这很好理解:子元素已经移到透视点之后了,也就是移到眼睛的后面了,我们是看不见眼睛后面的东西的!

6、perspective-origin
perspective-origin属性是3D变形中另一个重要属性,主要用来决定perspective属性的源点角度。它实际上设置了X轴和Y轴位置(或者说基点),在该位置观看者好像在观看该元素的子元素。

Pespective-origin: x-axis y-axis;

x-axis:

定义视图在x轴上的位置。默认值:50%。可能的参数值形式:left、center、right、length和%。

y-axis:

定义视图在y轴上的位置。默认值:50%。可能的参数值形式:top、center、bottom、length和%。

如果看了上面的介绍还是不太明白,没有能在大脑中形成一个清晰的概念,那么看下面这张截取的W3C官网的图:

在这里插入图片描述

(图片来源于:CSDN博主“我是新手”)

再来几个代码实栗就应该差不多懂了

(1)源点向左偏

.w1 {

perspective: 1000px;

}

.w2{

perspective: 1000px;

 perspective-origin: left center;

 }

.cube{

font-size: 4em;

width: 2em;

margin: 1.5em auto;

 transform-style: preserve-3d;

 }

在这里插入图片描述

源点左偏就相当于你正对这个正方体的时候,把头往左偏,你的眼睛所看到的画面,你的眼睛就相当于源点!

一个不够?!再来个栗子

(2)源点左偏同时上偏

.w1 {

perspective: 1000px;

 } 

.w2{

perspective: 1000px;

perspective-origin: left -100px;

 }

在这里插入图片描述

现在知道了perspective-origin改变源点的作用了吧,把源点当做自己的眼睛,改变源点的位置,就相当于改变你眼睛的位置!

7、transform-style属性
transform-style属性是3D空间一个重要属性,指定嵌套元素如何在3D空间中呈现。他主要有两个属性值:flat和preserve-3d

语法:transform-style: flat | preserve-3d

其中flat值为默认值,表示所有子元素在2D平面呈现。preserve-3d表示所有子元素在3D空间中呈现。

如果对一个元素设置了transform-style的值为flat,则该元素的所有子元素都将被平展到该元素的2D平面中进行呈现。沿着X轴或Y轴方向旋转该元素将导致位于正或负Z轴位置的子元素显示在该元素的平面上,而不是它的前面或者后面。如果对一个元素设置了transform-style的值为preserve-3d,它表示不执行平展操作,他的所有子元素位于3D空间中。

注意:transform-style属性需要设置在父元素中,并且高于任何嵌套的变形元素

是不是有点迷糊,没事,咱举个形象点的栗子

《喜羊羊与灰太狼》中的灰太狼都多多少少知道点吧,咱拿他来举例

首先把灰太狼这个整体形象看做父元素,灰太狼的鼻子,耳朵,嘴等是子元素

第一种状态:灰太狼被红太狼一锅拍在了衣服上(被拍成了扁平的)

在这里插入图片描述

现在就相当于灰太狼这个元素设置了transform-style,值为flat,不管你沿X、Y轴怎么转, 鼻子、耳朵、嘴等都是与灰太狼这个整体在一个平面,你看到的也就只有一个扁平的灰太狼

第二种状态:转头深情凝望
在这里插入图片描述

现在就相当于把transform-style的值设置为preserve-3d

可以看到灰太狼转头后(相当于把灰太狼这个元素以Y轴为轴心旋转了),鼻子、耳朵、嘴等都不是在同一个平面上,而是满满的立体感

现在来点专业的解释解释吧

在这里插入图片描述

上图的上部分:

当元素设置.rotate设置了flat值时,其子元素img不会根据translateZ()值摊开,而在同一平面旋转;

上图的下部分:

当元素.rotate设置了preserve-3d值时,其子元素img会根据translateZ()值摊开,不再会堆叠在一起。

注意:将元素的transform-style值设置为preserve-3d,就不能为了防止子元素溢出容器而将overflow值为hidden,如果设置了overflow:hidden同样可以迫使子元素出现在同一平面(和元素设置了transform-style为flat一样的效果)

8、backface-visibility
当你翻转一个元素的时候,你看到的是什么?通常情况下,我们应该看到的是元素的背面,这是正常的情况,但是有时候我们希望翻转一个元素后看到的是另一个元素。通过backface-visibility:hidden;属性,我们可以使一个元素在翻转之后消失,这是可以使用另一个元素放在它的背面,从而制作出一种元素翻转之后出现另一个元素的效果。

什么是backface-visibility
backface-visibility属性和3D transform效果相关,它用于决定当一个元素的背面面向用户的时候是否可见。例如下面图片展示的两个圆形元素,前面一个是正面,后面一个是背面。当它翻转到背面的时候,上面的文字应该是正面的镜像,这是默认的行为。

在这里插入图片描述

(以Y轴为轴心)

(2)应用实例
①旋转的甜甜圈

在这里插入图片描述

这个demo是理解backface-visibility属性的很好的例子。

当我们翻转了甜甜圈后,不希望再看到它的front面。因此我们需要另一幅代表甜圈背面的图片来取代原来的背面。

我们会将"front"面和"back"main放置在相同的位置上,"front"面位于"back"面的前面。"front"面使用backface-visibility: hidden;来隐藏背面。它们会沿Y轴同步旋转,转动背面时,"front"面消失,另一幅图片被展示出来。

关键代码:

img {

  position: absolute;

  animation: turn 2s infinite;

}

  

.donut-front {

  z-index: 5;

  backface-visibility: hidden;

}

  

@keyframes turn {

  to {

    transform: rotateY(360deg);

  }

}          

两张图片都使用相同的动画,只是第一张图片在旋转到背面时就被隐藏起来,这是第二张图片就自然的展示出来。

②洒落的咖啡

在这里插入图片描述
(以Y轴为轴心)

这个demo中有两个咖啡杯图片:一个是杯子的正面,一个杯子的背面。咖啡的水滴是一幅单独的图片,开始时它是隐藏的,它被在X轴上旋转了180度,这使得我们开始时看到的是它的背面,又因为设置了backface-visibility: hidden;,因此它是不可见的。

关键代码:

img {

  position: absolute;

  animation: turn-over 2s 700ms infinite;

}

  

.cup-front {

  z-index: 3;

  backface-visibility: hidden;

}

  

.coffee-drip {

  position: absolute;

  transform: rotateX(180deg);

  backface-visibility: hidden;

  animation: spill 2s infinite;

  animation-delay: 700ms;

}

  

@keyframes turn-over {

  to {

    transform: rotateX(-180deg);

  }

}

  

@keyframes spill {

  to {

    transform: translateY(200px);

  }

}  

更多使用CSS3 backface-visibility属性制作翻转动画效果

http://www.htmleaf.com/Demo/201504151687.html

实际应用-CSS 3D开门动画
演示效果:

在这里插入图片描述
(开门3D效果,有声音光线变化)

CSS代码:@charset “utf-8”;

/* CSS Document */



.door-box {

    max-width: 100%;

    width: 375px;

height: 628px;

    margin: 40px auto;

    //background-color: #2a273c;

background-image: url(木纹地板.jpg);

    font-family: STHeiTi, SimHei;

    overflow: hidden;

    position: relative;

    z-index: 1;

}

.door-box.active {

    animation: flyIntoRoom 1s both;

}

.door-box div {

    position: absolute;

}

.wall {

    left: 0;

top: 0;

right: 0;

bottom: 46px;

    border-bottom: 3px solid #211820;

    background-color: #768bb6;

    max-height: calc(1.8 * (375px - 80px));

    margin: auto;

    box-shadow: 0 -200px #768bb6;

}

.door-border {

    top: 28px;

    left: 40px;

    right: 40px;

    bottom: 0;

    border: 3px solid #211820;

    border-radius: 2px 2px 0 0;

    border-bottom: 0;

    background-color: rgba(33,26,26,1.00);

}

.door-frame {

    top: 10px;

left: 9px;

right: 9px;

bottom: 0;

    border: 3px solid #211820;

    border-radius: 2px 2px 0 0;

    border-bottom: 0;

    background-image: url(卧室.jpg);

background-size: 200% 100%;

    -webkit-perspective: 1200px;

    perspective: 1200px;

}

.door {

    left: 0; top: 0; right: 0;  bottom: 0;

    -webkit-transform-style: preserve-3d;

    transform-style: preserve-3d;

    transform-origin: left;

    transform: rotateY(0deg);

    -webkit-backface-visibility: hidden;

    backface-visibility: hidden;

}

.door-face-1,

.door-face-0 {

    left: -3px; top: -3px; right: -3px; bottom: -3px;

    border: 3px solid rgba(33,26,26,1.00);

   

background-image: url(木门.jpg);

background-size: 100% 100%;

}

.door-face-0 {

    transform: translateZ(-12px);

}

.door-face-1 {

    transform: translateZ(0);

}

.door-face-2 {

    height: 6px;

    left: -3px; right: -3px; top: 0;

    border: 3px solid #211820;

    border-radius: 2px;

    background-color: rgba(33,26,26,1.00);

    transform: translate3D(0, -7.5px, -6px) rotateX(90deg);

}

.door-face-3 {

    width: 6px;

    top: -3px; right: 0;

bottom: -3px;

    border: 3px solid #211820;

    border-radius: 2px;

    background-color: rgba(33,26,26,1.00);

    transform: translate3D(7.5px, 0, -6px) rotateY(90deg);

}

/*光线*/

.light {

    left: 0; top: 0; bottom: 0;

    background:rgba(219,207,161,1);

    width: 1000px;

    transform: translateZ(-13px);

}

/*门牌*/

.door-card {

    width: 165px;

height: 60px;

    line-height: 60px;

    background-color:rgba(55,44,45,0.7);

    top: 60px;

left: 0;

right: 0;

    margin: auto;

    text-align: center;

    font-size: 30px;

    border: 3px solid;

    border-radius: 10px;

}

.door-btn {

    left: 0; right: 0;

    text-align: center;

    margin-top: 140px;

    font-size: 24px;

    color: #9dbce3;

    line-height: 36px;

}

.door-in {

    width: 104px; height: 40px;

    border-radius: 40px;

    border: 2px solid;

    line-height: 40px;

    background-color: #eacc86;

    font-family: inherit; font-size: 24px;

    padding: 0; margin: 10px 0;

}

/* 动画 */

@keyframes flyIntoRoom {

    from {

        transform: scale(1) translateZ(0);

        opacity: 1;

    }

    to {

        transform: scale(2) translateZ(100px);

        opacity: 0;

    }

}

.room-img {

    position: absolute;

    width: 375px;

max-width: 100%;

    left: 0; right: 0;

top: 40px;

    margin: auto;

}

HTML代码

<!doctype html>

<html>

<head>

<meta charset="utf-8">

<title>3D开门动画</title>

<link href="style.css" rel="stylesheet" type="text/css">

</head>



<body>

<div id="doorBox" class="door-box">

    <div class="wall">

        <div class="door-border">

            <div class="door-frame">

                <!-- 门 -->

                <div id="door" class="door">

                    <!-- 门后的光线 -->

                    <div id="light" class="light" style="opacity: .8;" hidden=""></div>

                    <!-- 门后 -->

                    <div class="door-face-0"></div>

                    <!-- 三个面 -->

                    <div class="door-face-2"></div>            

                    <div class="door-face-1">

                        <!-- 门上的挂牌 -->

                        <div class="door-card">我的卧室</div>

                        <!-- 进入按钮 -->

                        <div class="door-btn">

                            <button id="doorBtnIn" class="door-in">进入</button>

                        </div>

                    </div>

                    <div class="door-face-3"></div>

                </div>

            </div>

        </div>

    </div>

</div>

<!-- 书房 -->

<img src="木纹地板.jpg" class="room-img" width="375" height="500">

<div hidden><audio id="audioOpen" src="./open.mp3" preload></audio></div>



</body>



</html>

JS代码:

<script>

// 门,光线这类运动元素

var eleDoor = document.getElementById('door');

var eleLight = document.getElementById('light');

var eleDoorBox = document.getElementById('doorBox');

// 开门音效mp3

var eleAudioOpen = document.getElementById('audioOpen');

// 开门动画

var percentDoor = 0;

var fnOpenDoor = function () {

percentDoor++;

// 门完全打开后,进入下一个画面

if (percentDoor == 100) {

//eleDoorBox.classList.add('active');

return;

}

// 门打开

eleDoor.style.transform = 'rotateY('+ (-90 * percentDoor / 100) +'deg)';

eleLight.removeAttribute('hidden');

// 光线变化

eleLight.style.opacity = 0.8 - 0.9 * percentDoor / 100;



setTimeout(fnOpenDoor, 16);

};

document.querySelector('#doorBtnIn').addEventListener('click', function () {

eleAudioOpen.play();

fnOpenDoor();

});

</script>
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值