CSS3带你实现3D转换效果
前言
在css3中允许使用3D转换来对元素进行格式化,在原本只是2D转化的平面中引入了Z轴。在这之前我们讲解了css3中的2D转换,也就是二维空间变换,本篇的3D转换就是基于原来的2D转换而来,与2D转换的功能相似。
三维坐标系
相信学过数学的效果版对这一概念多多少少是知道的,我们要想有一个3D空间效果,也就是立体空间感,比如:正方体、长方体.....再比如我们生活所居住的房间也是3D立体空间的,主要有X轴、Y轴Z轴共同组成

x轴 : 水平向右,x右边是正值,左边是负值。
y轴 : 垂直向下,y下面是正值,上面是负值。
z轴 : 垂直屏幕,往外面是正值,往里面是负值。
转换属性
| 属性 | 描述 |
| transform | 使得元素向2D或3D转换 |
| transform-origin | 改变转换元素的位置 |
| transform-style | 规定被嵌套元素如何在 3D 空间中显示 |
| perspective | 规定 3D 元素的透视效果 |
| perspective-origin | 规定 3D 元素的底部位置 |
| backface-visibility | 定义元素在不面对屏幕时是否可见 |
这里transform 属性和transform-origin 属性在前一篇《有趣的transform形变》中已经讲解了,这里就不再细说。不同的是在3D转换中,transform-origin 属性会接收第三个值,表示Z轴方向位置
(1)transform-style
transform-style设置元素的子元素是位于 3D 空间中还是平面中。
语法:
div{
transform-style: flat|preserve-3d;
}
- flat:设置元素的子元素位于该元素的平面中(子元素不设置3D空间)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.box{
position: relative;
width: 200px;
height: 200px;
margin: 100px auto;
transition: .5s;
/* flat:子元素不存在3D空间 */
transform-style: flat;
background-color: #eee;
}
.box:hover{
transform: rotateY(60deg);
}
.s{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: pink;
}
.s2{
background-color: orange;
transform: rotateX(45deg);
}
</style>
</head>
<body>
<div class="box">
<div class="s s1"></div>
<div class="s s2"></div>
</div>
</body>
</html>
设置flat值,子元素就只位于平面中,效果如下:

- preserve-3d:设置元素的子元素应用于3D空间中
基于上述栗子,将transform-style 属性值改为preserve-3d :
.box{
/* 让子元素保持3d立体空间环境 */
transform-style: preserve-3d;
}
得到3D空间效果:

3D视觉是不是感觉一下就来啦~
(2)perspective
perspective指定了观察者与 z=0 平面的距离,使具有三维位置变换的元素产生透视效果。如果不指定透视,则Z轴空间中的所有点将平铺到同一个2D视平面中,并且变换结果中将不存在景深概念z>0 的三维元素比正常大,而 z<0 时则比正常小,大小程度由该属性的值决定
“perspective”本身就具有透视的意思,就是设置用于户和元素3D空间Z平面之间的距离(视距),简单理解就是将电脑屏幕当做一个平面,用户眼睛到屏幕的垂直方向。值越大用户与屏幕距离越远,视觉效果很小,值越小3D效果就越明显。

语法:
div{
perspective:none | <length>
}
- none:默认值,与 0 相同,不设置透视
- length:元素距离视图的距离,以像素计
这里还是以上述栗子进行演示:
body{
perspective: 900px;
}
或者
.box{
perspective: 900px;
}
只要设置在父盒子上就可以,效果如下:

从第一眼就可以看出与上面不同,没有设置景深是这样:

设置了景深是这样的:

注意:perspective属性只影响 3D 转换元素,并且同时使用perspective-origin 属性,可以改变 3D 元素的底部位置
(3)perspective-orgin
perspective-origin 属性定义 3D 元素所基于的 X 轴和 Y 轴。该属性允许您改变 3D 元素的底部位置。
语法:
perspective-origin: x-axis y-axis;
x-position:指定消失点的横坐标,其值有以下形式:
<length-percentage>长度值或相对于元素宽度的百分比值,可为负值。left, 关键字,0值的简记。center, 关键字,50%的简记。right, 关键字,100%的简记。
y-position:指定消失点的纵坐标,其值有以下形式:
<length-percentage>长度值或相对于元素高度的百分比值,可为负值。top, 关键字,0值的简记。center, 关键字,50%的简记。bottom, 关键字,100%的简记
介绍完语法使用,我们知道了怎么取值,下面还是基于上述例子继续演示:
- 值为长度值:
.box{
perspective-origin: 300px;
}
效果如下:

- 值为关键字:
.box{
perspective: 900px;
perspective-origin: left;
}
效果如下:

- 值为百分比:
.box{
perspective: 900px;
perspective-origin: 300%;
}
效果如下:

- 两个值:
.box{
perspective: 900px;
perspective-origin: left top;
}
效果如下:

(4)backface-visibility
backface-visibility指定当元素背面朝向观察者时是否可见
元素的背面是其正面的镜像,虽然在 2D 中不可见,但是当变换导致元素在 3D 空间中旋转时,背面可以变得可见。 (此属性对 2D 变换没有影响,它没有透视。)
语法:
backface-visibility: visible|hidden;
- visible:默认值。 背面是可见的。
- hidden:背面是不可见的
这里借鉴了MDN上面的例子:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.showbf div {
backface-visibility: visible;
} .hidebf div {
backface-visibility: hidden;
}
.container {
width: 150px;
height: 150px;
margin: 75px 0 0 75px;
border: none;
} .cube {
width: 100%;
height: 100%;
perspective: 550px;
perspective-origin: 150% 150%;
transform-style: preserve-3d;
} .face {
display: block;
position: absolute;
width: 100px;
height: 100px;
border: none;
line-height: 100px;
font-family: sans-serif;
font-size: 60px;
color: white;
text-align: center;
} .front {
background: rgba(0, 0, 0, 0.3);
transform: translateZ(50px);
} .back {
background: rgba(0, 255, 0, 1);
color: black;
transform: rotateY(180deg) translateZ(50px);
} .right {
background: rgba(196, 0, 0, 0.7);
transform: rotateY(90deg) translateZ(50px);
} .left {
background: rgba(0, 0, 196, 0.7);
transform: rotateY(-90deg) translateZ(50px);
} .top {
background: rgba(196, 196, 0, 0.7);
transform: rotateX(90deg) translateZ(50px);
} .bottom {
background: rgba(196, 0, 196, 0.7);
transform: rotateX(-90deg) translateZ(50px);
} th, p, td {
background-color: #EEEEEE;
margin: 0px;
padding: 6px;
font-family: sans-serif;
text-align: left;
}
</style>
</head>
<body>
<table>
<tr>
<th><code>backface-visibility: visible;</code></th>
<th><code>backface-visibility: hidden;</code></th>
</tr>
<tr>
<td>
<div class="container">
<div class="cube showbf">
<div class="face front">1</div>
<div class="face back">2</div>
<div class="face right">3</div>
<div class="face left">4</div>
<div class="face top">5</div>
<div class="face bottom">6</div>
</div>
</div>
<p>
Since all faces are partially transparent,
the back faces (2, 4, 5) are visible
through the front faces (1, 3, 6).
</p>
</td>
<td>
<div class="container">
<div class="cube hidebf">
<div class="face front">1</div>
<div class="face back">2</div>
<div class="face right">3</div>
<div class="face left">4</div>
<div class="face top">5</div>
<div class="face bottom">6</div>
</div>
</div>
<p>
The three back faces (2, 4, 5) are
hidden.
</p>
</td>
</tr>
</table>
</body>
</html>
3D转换
旋转单位:deg(角度)、rad(弧度)、grad(梯度)、turn(圈)
弧度 = 角度*π/180
grad = 360度(一圈)
(1)3D位移
3D位移在2D基础上多加了一个可以z轴移动的方向
3D位移主要演示translateZ和translate3d两个属性:
translate3d() CSS 函数在3D空间内移动一个元素的位置,这个移动由一个三维向量来表达,分别表示他在三个方向上移动的距离
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>3D位移</title>
<style>
body{
perspective: 800px;
}
.box{
position: relative;
width: 200px;
height: 200px;
margin: 100px auto;
transition: .5s;
background-color: pink;
text-align: center;
line-height: 200px;
}
.box:hover{
/* transform: translateX(50px) translateY(100px) translateZ(200px); */
/* 简写 */
transform: translate3d(50px,100px,200px);
}
</style>
</head>
<body>
<div class="box">3D位移</div>
</body>
</html>
效果如下:

注意:
- 首先要设置
perspectiv属性在被观察元素的父盒子上,不然不会有Z轴效果。 - 如果只是单独设置Z轴视距,可以直接使用translateZ属性。
- Z轴设置的值越大,距离我们眼睛就越近,也就是简单理解元素被放大了
- Z轴设置的值越小,或者为负数,则会离我们眼睛越远,元素缩小
(2)3D旋转
rotateX:让元素围绕X轴转
rotateY:让元素围绕Y轴旋转
rotateZ:让元素围绕Z轴旋转
rotate3d:让元素围绕固定轴旋转不变形
旋转量由角度决定,角度为正则顺时针旋转,反之逆时针旋转
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>3D旋转</title>
<style>
body{
perspective: 800px;
}
.box{
position: relative;
width: 200px;
height: 200px;
margin: 100px auto;
transition: .5s;
background-color: pink;
text-align: center;
line-height: 200px;
}
.box:hover{
transform: rotateX(180deg); /* X轴旋转180° */
transform: rotateY(180deg); /* Y轴旋转180° */
transform: rotateZ(180deg); /* Z轴旋转180° */
}
</style>
</head>
<body>
<div class="box">3D旋转</div>
</body>
</html>
X轴旋转效果:

Y轴旋转效果:

Z轴旋转效果:

这里单独将rotate3d函数拎出来讲
语法:
rotate3d(x, y, z, a)
取值分析:
- x:可以是0到1之间的数值,表示旋转轴X坐标方向的矢量
- y:可以是0到1之间的数值,表示旋转轴Y坐标方向的矢量
- z:可以是0到1之间的数值,表示旋转轴Z坐标方向的矢量
- a:表示旋转角度。正的角度值表示顺时针旋转,负值表示逆时针旋转
也就是说 rotateX(a) === rotate3d(1,0,0,a) 、 rotateY(a) === rotate3d(0,1,0,a) 、 rotateZ(a) === rotate3d(0,0,1,a)
.box:hover{
transform: rotate3d(1,1,0,50deg); /* 表示在X轴和Y轴旋转50° */
}
效果如下:

.box:hover{
transform: rotate3d(1,1,1,1turn); /* 围绕3轴旋转一圈 */
}
效果如下:

综合案例
基于上述所学内容,我们来实操做一个3D盒子旋转:
html结构 :
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>3D盒子旋转</title>
<link rel="stylesheet" href="css/index.css" />
</head>
<body>
<section>
<div><img src="data:images/1.jpg" alt="" /></div>
<div><img src="data:images/2.jpg" alt="" /></div>
<div><img src="data:images/3.jpg" alt="" /></div>
<div><img src="data:images/4.jpg" alt="" /></div>
<div><img src="data:images/5.jpg" alt="" /></div>
<div><img src="data:images/6.jpg" alt="" /></div>
<div><img src="data:images/1.jpg" alt="" /></div>
<div><img src="data:images/2.jpg" alt="" /></div>
<div><img src="data:images/3.jpg" alt="" /></div>
<div><img src="data:images/4.jpg" alt="" /></div>
<div><img src="data:images/5.jpg" alt="" /></div>
<div><img src="data:images/6.jpg" alt="" /></div>
</section>
</body>
</html>
css部分 :
* {
/* 初始化 */
padding: 0;
margin: 0;
}
body {
/* 弹性布局*/
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
/* 视距 */
perspective: 1000px;
}
section {
position: relative;
width: 150px;
height: 150px;
/* 让子元素保留其3D位置 */
transform-style: preserve-3d;
/* 动画 名称 时长 linear 是匀速运动 infinite是无限次播放 */
animation: rotate 5s linear infinite;
}
section div {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #fff;
transition: all 1s;
}
section div img {
width: 100%;
height: 100%;
}
/* 这里使用的伪类选择器 */
section div:nth-child(1) { /* 选择第1个元素 */
transform: translateZ(75px);
}
section:hover div:nth-child(1) {
transform: translateZ(200px);
}
section div:nth-child(2) { /* 选择第2个元素 */
transform: rotateX(-180deg) translateZ(75px);
}
section:hover div:nth-child(2) {
transform: rotateX(-180deg) translateZ(200px);
}
section div:nth-child(3) { /* 选择第3个元素 */
transform: rotateX(90deg) translateZ(75px);
}
section:hover div:nth-child(3) {
transform: rotateX(90deg) translateZ(200px);
}
section div:nth-child(4) { /* 选择第4个元素 */
transform: rotateX(-90deg) translateZ(75px);
}
section:hover div:nth-child(4) {
transform: rotateX(-90deg) translateZ(200px);
}
section div:nth-child(5) { /* 选择第5个元素 */
transform: rotateY(90deg) translateZ(75px);
}
section:hover div:nth-child(5) {
transform: rotateY(90deg) translateZ(200px);
}
section div:nth-child(6) { /* 选择第6个元素 */
transform: rotateY(-90deg) translateZ(75px);
}
section:hover div:nth-child(6) {
transform: rotateY(-90deg) translateZ(200px);
}
section div:nth-child(7) { /* 选择第7个元素 */
transform: translateZ(75px);
}
section div:nth-child(8) { /* 选择第8个元素 */
transform: rotateX(-180deg) translateZ(75px);
}
section div:nth-child(9) { /* 选择第9个元素 */
transform: rotateX(90deg) translateZ(75px);
}
section div:nth-child(10) { /* 选择第10个元素 */
transform: rotateX(-90deg) translateZ(75px);
}
section div:nth-child(11) { /* 选择第11个元素 */
transform: rotateY(90deg) translateZ(75px);
}
section div:nth-child(12) { /* 选择第12个元素 */
transform: rotateY(-90deg) translateZ(75px);
}
/* 定义动画 */
@keyframes rotate {
0% {
transform: rotateY(0) rotateX(0);
}
100% {
transform: rotateY(360deg) rotateX(360deg);
}
}
效果如下

CSS3带你实现3D转换效果的更多相关文章
- CSS3 transform变形(3D转换)
一.三维坐标 空间中三维坐标如下图所示: 向上为-Y,向下为+Y,向左为-X,向右为+X,向前为+Z,向后为-Z. 二.perspective(n)为 3D 转换元素定义透视视图 perspectiv ...
- CSS3的2D与3D转换
2D和3D转换涉及到数学中的知识,作为一个数学专业的毕业生,不研究一下岂不是对不起自己的专业? 首先来看几个参数: 1.transform-origin:origin(起源,起点),也即变形的起点,在 ...
- CSS笔记(十二)CSS3之2D和3D转换
参考:http://www.w3school.com.cn/css3/css3_2dtransform.asp 2D Transform 方法 函数 描述 matrix(n,n,n,n,n,n) 定义 ...
- css3动画2D、3D转换
css3动画的2D.3D转换代码: <!DOCTYPE html> <html lang="en"> <head> <meta chars ...
- 使用JS与CSS3的翻转实现3D翻牌效果
之前我们有讨论过使用CSS3如何实现网页水平翻转的效果,而这次我们介绍的是翻转效果更深一层的应用——3D翻牌效果. 这里我们需要使用flip中轴翻转实现,又因为是3D效果,如果希望呈现一定的3D视角, ...
- css3学习总结8--CSS3 3D转换
3D 转换 1. rotateX() 2. rotateY() otateX() 方法 通过 rotateX() 方法,元素围绕其 X 轴以给定的度数进行旋转. 示例: div { transform ...
- HTML5和CSS3实现3D转换效果 CSS3的3D效果
上次,我们一起研究了css3的2d模块,这次我们一起来看一下css3的3d模块. 首先,我们来了解一下3d的坐标系,x轴在屏幕上为水平方向,y轴为垂直方向,而z轴为垂直于屏幕的方向. 不理解的话可以参 ...
- jquery和CSS3带倒影的3D万花筒旋转动画特效效果演示
<!DOCTYPE html> <html> <head> <title></title> <meta charset='utf-8' ...
- [web前端] css3 transition属性实现3d动画效果
cp from : https://www.cnblogs.com/chrxc/p/5123375.html transition属性是一个很强大的3d动画属性,我动手试了一下,很多在网上很火的网页动 ...
随机推荐
- 『无为则无心』Python函数 — 29、Python变量和参数传递
目录 1.Python的变量 (1)Python变量不能独立存在 (2)变量是内存中数据的引用 (3)注意点 2.了解变量的引用 3.Python的参数传递(重点) (1)示例 (2)结论 (3)总结 ...
- 论文翻译:2020_A Robust and Cascaded Acoustic Echo Cancellation Based on Deep Learning
论文地址:https://indico2.conference4me.psnc.pl/event/35/contributions/3364/attachments/777/815/Thu-1-10- ...
- Docker下安装Nacos
1:使用docker获取nacos服务镜像 docker pull nacos/nacos-server(不加版本号表示获取最新版本) 2:查看是否成功下载nacos镜像 docker images ...
- python appium使用uiselector定位时,提示 Could not parse UiSelector argument: 'XXX' is not a string
运行自动化代码,appium返回Could not parse UiSelector argument: 'XXX' is not a string,其中的xxx就是定位的元素 解决方案:外侧用 '' ...
- redis 加锁与解锁的详细总结,解决线程并发导致脏数据
1.前言 对每个controller来说都是全新且单独的,原因是多线程,如果多个请求操作共有的数据,这样的并发操作会导致脏数据 怎么解决? mysql可以使用积极锁解决, 这里讲解的是redis的解决 ...
- nuxt服务端渲染
<template> <div class="page"> page is search <ul> <li v-for="(it ...
- SQL高级优化(五)之执行计划
一.explain 执行计划:在MySQL中可以通过explain关键字模拟优化器执行SQL语句,从而知道MySQL是如何处理SQL语句的. explain:MySQL执行计划的工具,查看MySQL如 ...
- asyncio异步编程
1. 协程 协程不是计算机提供,程序员认为创造 协程(Coroutine),也可以被称为微线程,是一种用户态内的上下文切换技术,其实就是一个线程实现代码块相互切换执行.例如: def func1(): ...
- [未完] Linux 4.4 USB —— spiflash模拟usb大容量存储设备 调试记录 Gadget Mass Stroage
linux 4.4 USB Gadget Mass Stroage 硬件平台: licheepi nano衍生 调试记录 驱动信息 │ This driver is a replacement for ...
- 【从小白到专家】 Istio专题之七:30分钟讲透Istio访问与控制
本文为Istio系列专题之七--Istio访问与控制.Istio通过身份认证.授权.多重安全策略,来保证微服务的安全,实现代码无侵入性.有时我们需要对微服务间的相互访问进行控制,比如满足某些条件的微服 ...