Web 技术飞速发展,但是绝大数技术人员并没有跟上其脚步,博主就是其中一员。当我们还在琢磨上一代技术时,那些技术前沿的弄潮儿开始打造新一代技术。这里聊一聊非高频却十分炫酷的 3D 技术,使用 CSS3 即可实现。
二维与三维
在说到三维之前,我们先聊一聊二维。
二维很好理解,即平面。我们使用 x 轴和 y 轴就可以轻松表示。
三维是在二维的基础上增加了一个维度。这个稍微有点难理解,可以参考下图:
我们在网页里面构造一个正方形非常简单,但是如果想构造一个正方体,那就麻烦了。正常情况下,页面是一个二维空间,所以无法构造立体图。如果想构造立方体,我们必须在三维空间里面。
相关属性
先认识下 CSS3 中提供的一些 3d 属性:
- perspective:规定 3D 元素的透视效果。
- perspective-origin:规定 3D 元素的底部位置。
- transform-style:规定被嵌套元素如何在 3D 空间中显示。
- transform-origin:允许你改变被转换元素的位置。
- transform:向元素应用 2D 或 3D 转换。
- backface-visibility:定义元素在不面对屏幕时是否可见。
perspective
这个属性表示眼睛离物体的距离,并且这个值是非负的。在 Web 3d 的世界中,该值表示屏幕离物体的距离。
由此不难理解,该值越大,界面呈现的物体越小。该值越小,界面呈现的物体越大。
perspective-origin
表示视线灭点的位置,默认值是物体的中心。可以简单理解为视线的焦点。
transform-style
表示空间内元素的展示模式,有平面和立体两种,flat 和 preserve-3d。
perspective
、perspective-origin
、transform-style
这三个属性都作用于父元素,即 3d 物体的元素的上级元素。
backface-visibility
表示当元素不面向屏幕时是否可见。如果我们把一个元素翻转 180 度,并且不想看到这个元素,那么我们将 backface-visibility
设为 false
即可。
transform
和transform-origin
不在赘述,在上一篇博文里有讲述。
实战
理论与实践结合,我们才能更好的理解。这里结合两个小例子,进一步巩固前面的理论基础。
正方体
正方体的实现思路就是利用六个面,经过旋转变化组合而成。
前后两个面,通过 z 轴方向的偏移可以得到。
左右两个面,需要先经过一次 y 轴方向的旋转,再经过 z 轴方向的偏移。
上下两个面,需要先经过一次 x 轴方向的旋转,再经过 z 轴方向的偏移。
关键代码
<div class="cube">
<div class="c1"><img src="./img/1.jpg" alt=""></div>
<div class="c2"><img src="./img/2.jpg" alt=""></div>
<div class="c3"><img src="./img/3.jpg" alt=""></div>
<div class="c4"><img src="./img/4.jpg" alt=""></div>
<div class="c5"><img src="./img/5.jpg" alt=""></div>
<div class="c6"><img src="./img/6.jpg" alt=""></div>
</div>
.cube {
position: relative;
transform-style: preserve-3d;
animation: move 10s linear infinite;
border: 1px solid #ccc;
width: 200px;
height: 200px;
}
@keyframes move {
from {
transform: rotateX(0deg) rotateY(0deg);
}
to {
transform: rotateX(-360deg) rotateY(360deg);
}
}
.cube div {
position: absolute;
width: 200px;
height: 200px;
border: 1px solid #ccc;
text-align: center;
line-height: 100px;
box-shadow: inset 0 0 20px #3333FF;
opacity: .8;
}
img {
width: 100%;
height: 100%;
}
.c1 {
transform: translateZ(100px);
}
.c2 {
transform: rotateY(180deg) translateZ(100px);
}
.c3 {
transform: rotateY(90deg) translateZ(100px);
}
.c4 {
transform: rotateY(270deg) translateZ(100px);
}
.c5 {
transform: rotateX(-90deg) translateZ(100px);
}
.c6 {
transform: rotateX(90deg) translateZ(100px);
}
3d轮播图
效果图就是博文开头那张,为了方便阅读,这里也放置一张。
思路和上个正方体一样,细节可以参考代码。
<div class="container">
<h2>埃菲尔铁塔</h2>
<ul>
<li><img src="./img/1.jpg" alt=""></li>
<li><img src="./img/2.jpg" alt=""></li>
<li><img src="./img/3.jpg" alt=""></li>
<li><img src="./img/4.jpg" alt=""></li>
<li><img src="./img/5.jpg" alt=""></li>
<li><img src="./img/6.jpg" alt=""></li>
</ul>
<div class="btn-wrapper">
<button class="prev">上一张</button>
<button class="next">下一张</button>
</div>
</div>
.container {
width: 800px;
height: 400px;
border: 1px solid #ccc;
margin: 50px auto 0 auto;
display: flex;;
align-items: center;
justify-content: center;
perspective: 800px;
position: relative;
background-color: #99CCCC;
border-radius: 10px;
}
ul {
position: relative;
width: 200px;
height: 200px;
transform-style: preserve-3d;
transition: transform 1s ease;
}
li {
position: absolute;
width: 200px;
height: 200px;
opacity: .9;
box-shadow: 0px 0px 5px #3399FF;
border-radius: 5%;
}
li:nth-child(1) {
transform: rotateY(0) translateZ(180px);
}
li:nth-child(2) {
transform: rotateY(60deg) translateZ(180px);
}
li:nth-child(3) {
transform: rotateY(120deg) translateZ(180px);
}
li:nth-child(4) {
transform: rotateY(180deg) translateZ(180px);
}
li:nth-child(5) {
transform: rotateY(240deg) translateZ(180px);
}
li:nth-child(6) {
transform: rotateY(300deg) translateZ(180px);
}
img {
width: 100%;
height: 100%;
border-radius: 5%;
}
.btn-wrapper {
position: absolute;
left: 50%;
bottom: 10px;
transform: translateX(-50%);
}
button {
padding: 8px 25px;
font-size: 14px;
color: #333;
background-color: #3399FF;
color: #fff;
border: none;
outline: none;
border-radius: 4px;
}
button:last-child {
margin-left: 20px;
}
h2 {
position: absolute;
top: 10px;
left: 50%;
transform: translateX(-50%);
color: #333;
}
var cities = [
'埃菲尔铁塔',
'故宫',
'凯旋门',
'长城',
'黄鹤楼',
'悉尼歌剧院'
]
var prev = document.querySelector('.prev');
var next = document.querySelector('.next');
var ul = document.querySelector('ul');
var h2 = document.querySelector('h2');
var deg = 0
var i = 0
prev.addEventListener('click', function() {
deg += 60
i--
if (i < 0) {
i = 5
}
h2.innerHTML = cities[i]
ul.style.transform = `rotateY(${deg}deg)`
})
next.addEventListener('click', function() {
deg -= 60
i++
if (i > 5) {
i = 0
}
h2.innerHTML = cities[i]
ul.style.transform = `rotateY(${deg}deg)`
})
小结
这里主要是博主自己的学习记录,很多细节如果有不明白的,可以参考: