前面我们已经介绍过了2D转换,那么我们即将学习的3D转换又是什么呢,它跟2D转换有什么不同呢?
在我们日常生活的环境就是3D的,我们多看到的物体也都是3D的,而我们拍的照片就是3D物体在2D平面中呈现的样子 。
3D的特点
- 近大远小(离我们眼睛越近看上去越大,而离眼睛越远则看上去越小)
- 物体后面遮挡不可见
根据这些特点我们就可以在网页上模拟构建出3D效果。
三维坐标系
我们前面讲过的2D是一个平面坐标系,而3D则是三维坐标系。三维坐标系其实就是指立体空间,立体空间是由3个轴共同组成的。
- x轴:水平向右。x右边是正值,左边是负值
- y轴:垂直向下。y下面是正值,上面是负值
- z轴:垂直屏幕。往外面是正值,往里面是负值
在我们的网页中的左边原点就是我们屏幕的左上角。
3D转换
3D转换中我们主要来学习工作中最常用的3D位移和3D旋转
主要知识点
- 3D位移:translate3d(x,y,z)
- 3D旋转:rotate3d(x,y,z)
- 透视: perspective
- 3D呈现transfrom-style
3D移动 - translate3d
3D移动在2D移动的基础上多加了一个可以移动的方向,就是z轴方向
- transform:translateX(200px)仅在x轴上移动
- transform:translateY(200px)仅在y轴上移动
- transform:translateZ(200px)仅在z轴上移动
- transform:translate3d(x,y,z)其中x、y、z分别指要移动的轴的方向的距离
下面我们用代码来演示一下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3d demo</title>
<style>
div {
width: 200px;
height: 200px;
background-color: pink;
transform: translateX(100px) translateY(100px) translateZ(100px);
}
</style>
</head>
<body>
<div></div>
</body>
</html>
在上面这段代码中,我们让这个粉色盒子分别沿着x轴、y轴和z轴各移动了100像素,但是当我们运行起来是发现,z轴方向好像并没有明显的变化。这是因为z轴方向上的移动需要借助透视才能看出效果。接下来我们来看看什么是透视。
透视perspective
perspective 属性定义 3D 元素距视图的距离,以像素计。该属性允许您改变 3D 元素查看 3D 元素的视图。当为元素定义 perspective 属性时,其子元素会获得透视效果,而不是元素本身。
我们平时去电影院看3D电影时,如果直接用眼睛去看其实并看不出明显的3D效果,而是每次电影院都会发给我们一个3D眼镜,那么借助3D眼镜我们再看电影3D效果就非常明显了。那么在我们的网页中如果也需要让我们看到的3D效果明显一些,那就需要借助透视了
- 如果想要在网页产生3D效果需要借助透视(理解成3D物体投影在2D平面上)
- 模拟人类的视觉位置,借助perspective和translateZ可以模拟实现元素的近大远小的效果
- 透视的单位是像素
- 透视越小效果越明显
注意:
- 透视必须写在被观察元素的父盒子上面
- perspective 属性只影响 3D 转换元素
- 要想改变translateZ实现近大远小效果,则必须要借助透视,否则translateZ是没有效果的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3d demo</title>
<style>
body{
perspective: 200px;
}
div {
width: 200px;
height: 200px;
background-color: pink;
transform: translateX(100px) translateY(100px) translateZ(100px);
}
</style>
</head>
<body>
<div></div>
</body>
</html>
上面的代码中我们给div的父元素body添加一个透视,这时再看这个粉色盒子发现明显比不加透视时变大了很多。这就是透视的作用。上面的示例可能还不够明显,接下来我们再看一个rotat3d的例子效果会更明显
3D旋转 rotate3d
3D旋转指可以让元素在三维平面内沿着x轴、y轴、z轴或自定义轴进行旋转
语法:
- transform:rotateX(Xdeg):沿着x轴正向旋转X度
- transform:rotateY(Ydeg):沿着y轴正向旋转Y度
- transform:rotateZ(Zdeg):沿着z轴正向旋转Z度
- transform:rotate3d(x,y,z,deg):沿着自定义轴旋转deg为旋转度数
对于元素的旋转方向也是正负之分的,那么如何区分元素旋转方向的正负呢,下面我们来学习一下左手准则,用我们的左手即可判断方向的正负
左手准则:
- 左手的手指指向x轴、y轴、z轴的正方向
- 其余手指的弯曲方向就是该元素沿着x轴、y轴、z轴旋转的方向
下面的代码是沿着x轴正向旋转的示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
#div1
{
position: relative;
height: 150px;
width: 150px;
margin: 50px;
padding:10px;
border: 1px solid black;
perspective:50;
-webkit-perspective:150; /* Safari and Chrome */
}
#div2
{
padding:50px;
position: absolute;
border: 1px solid black;
background-color: pink;
transform: rotateX(45deg);
-webkit-transform: rotateX(45deg); /* Safari and Chrome */
}
</style>
</head>
<body>
<div id="div1">
<div id="div2">HELLO</div>
</div>
</body>
</html>
上述代码中如果我们不加透视效果则运行后就是下面第一个图的样子,如果使用了透视则就是第二张图的样子,这样来看透视的作用就很明显了。
3D呈现 transform-style
transform-style 属性规定如何在 3D 空间中呈现被嵌套的元素。
注释:
- 该属性必须与 transform 属性一同使用
- 代码与透视一样必须写在父级元素上,但会作用在子元素上
语法:transform-style: flat | preserve-3d;
值 | 描述 |
---|---|
flat | 子元素将不保留其 3D 位置。 |
preserve-3d | 子元素将保留其 3D 位置。 |
下面来看个例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
body{
perspective: 300px;
}
.box{
position:relative;
width:200px;
height:200px;
margin:100px auto;
transition:all 1s;
transform-style: preserve-3d;
}
.box:hover{
transform:rotateY(45deg)
}
.box div{
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
background-color: pink;
}
.box div:last-child{
background-color:green;
transform:rotateX(60deg)
}
</style>
</head>
<body>
<div class="box">
<div></div>
<div></div>
</div>
</body>
</html>
上面代码中一个大盒子中嵌套两个小盒子,当我们鼠标悬浮到大盒子上时,我们先让绿色小盒子沿着X轴正向旋转60度,然后再让大盒子沿着Y轴正向旋转45度 。那么在我们不用transform-style修饰时会得到如下第一个图的效果,而使用了transform-style后会出现第二张图的样子。这个例子很好的描述了transform-style的作用(保留子元素的3D效果)。
案例
实现两个翻转的盒子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3d demo</title>
<style>
body{
perspective: 350px;
}
.box {
position: relative;
width: 200px;
height: 200px;
margin: 100px auto;
transform-style: preserve-3d;
transition: all 0.4s;
}
.box div {
position: absolute;
width: 200px;
height: 200px;
line-height: 200px;
text-align: center;
border-radius: 50%;
}
.box div:first-child {
background-color: pink;
z-index: 1;
}
.box div:last-child {
background-color: green;
transform: rotateY(180deg);
}
.box:hover{
transform: rotateY(180deg);
}
</style>
</head>
<body>
<div class="box">
<div>Hello</div>
<div>world</div>
</div>
</body>
</html>
3D导航栏案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3d demo</title>
<style>
.box {
position: relative;
transform-style: preserve-3d;
transition: all 0.4s;
}
.box div {
width: 200px;
height: 50px;
line-height: 50px;
text-align: center;
background-color:pink;
}
.box .shn {
background-color: green;
transform: translateY(-25px) translateZ(-25px) rotateX(-90deg)
}
.box:hover{
transform: translateY(-50px) rotateX(90deg);
}
li{
float: left;
list-style: none;
}
</style>
</head>
<body>
<ul>
<li>
<div class="box">
<div>导航一</div>
<div class="shn">导航一</div>
</div>
</li>
<li>
<div class="box">
<div>导航二</div>
<div class="shn">导航二</div>
</div>
</li>
<li>
<div class="box">
<div>导航三</div>
<div class="shn">导航三</div>
</div>
</li>
</ul>
</body>
</html>
旋转木马案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>旋转木马</title>
<style>
body {
perspective: 1000px;
}
section {
position: relative;
width: 300px;
height: 200px;
margin: 200px auto;
transform-style: preserve-3d;
animation: rotate 10s linear infinite;
background: url(caoyaolu.jpg) no-repeat center;
}
section div {
position: absolute;
width: 100%;
height: 100%;
background: url(timg.jfif) no-repeat;
}
section:hover {
animation-play-state: paused;
}
section div:first-child {
transform: translateZ(400px);
}
section div:nth-child(2) {
transform: rotateY(60deg) translateZ(400px);
}
section div:nth-child(3) {
transform: rotateY(120deg) translateZ(400px);
}
section div:nth-child(4) {
transform: rotateY(180deg) translateZ(400px);
}
section div:nth-child(5) {
transform: rotateY(240deg) translateZ(400px);
}
section div:nth-child(6) {
transform: rotateY(300deg) translateZ(400px);
}
@keyframes rotate {
0% {
transform: rotateY(0deg);
}
100% {
transform: rotateY(100deg);
}
}
</style>
</head>
<body>
<section>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</section>
</body>
</html>